I want to generate a vector of 100 values composed by [1 0]:
This is how I did it in Matlab:
n = 100;
Seq1 = [1 0]; % sequence of 1-0
Vector = repmat(Seq1,(n/2),1); % Creates n/2 sequences of 1-0
The result is a vector like: [1 0 1 0 1 0 1 0...]
Is there a way to get the same result with JavaScript?
You could mimic the function repmat with a while loop.
function repmat(array, count) {
var result = [];
while (count--) {
result = result.concat(array);
}
return result;
}
var nTrials = 100,
Seq1 = [1, 0],
Vector = repmat(Seq1, nTrials / 2);
console.log(Vector);
Assuming you're looking for a way to add a 1 and then a 0, not an array containing 1 and 0:
var myArray = [];
nTrials = 30;
for(i = 1; i<= nTrials/2; i++){
myArray.push(1);
myArray.push(0)
}
document.body.innerHTML = myArray[1];}
https://jsfiddle.net/6seqs6af/1/
FWIW, here is the full repmat implementation in JavaScript.
It uses arrow functions (=>) which isn't available in all browsers.
// Seq1 is an Array (1D vector). We need a Matrix which JavaScript doesn't have
// natively. But we can derive a Matrix type from an Array by adding
// `numberOfRows` and `numberOfColumns` properties as well as a `set` method
function Matrix(numberOfRows, numberOfColumns) {
this.numberOfColumns = numberOfColumns;
this.numberOfRows = numberOfRows;
this.length = numberOfColumns * numberOfRows;
this.fill();
}
Matrix.prototype = Array.prototype;
Matrix.prototype.set = function() {
for (var i = 0; i < arguments.length; i++) {
this[i] = arguments[i];
}
return this;
}
Matrix.prototype.toString = function() {
return this.reduce((acc, x, idx) => acc + (idx % this.numberOfColumns === this.numberOfColumns - 1 ? x + '\n' : x + ', '), '');
}
Matrix.prototype.at = function(row, column) {
return this[row * this.numberOfColumns + column];
}
// Repmap
// ======
function repmat(mat, repeatColumns, repeatRows) {
var numberOfColumns = mat.numberOfColumns * repeatColumns;
var numberOfRows = mat.numberOfRows * repeatRows;
var values = [];
for (var y = 0; y < numberOfRows; y++) {
for (var x = 0; x < numberOfColumns; x++) {
values.push(mat.at(y % mat.numberOfRows, x % mat.numberOfColumns));
}
}
var result = new Matrix(numberOfRows, numberOfColumns);
result.set.apply(result, values);
return result;
}
// Calculation
// ===========
var nTrials = 100;
var seq1 = new Matrix(1, 2);
seq1.set(1, 0);
var vector = repmat(seq1, nTrials / 2, 1);
console.log(vector.toString());
Related
I'm trying to filter out all lines as a result from HoughLine function in opencv. Currently just using getLines() function to get all lines then sorting them according to their rho value for each line. Then applying for loop to remove duplicates, problem is as follows:
In code if in (r1, θ1) and (r2, θ2) which I'm comparing in inner for loop for both either (r1,r2) positive or (r1,r2) negative (based on html canvas) then it's easy to filter them. But if either of them is positve or negative respectively then that line also gets included in finalLines array. Which can be explained through following figure:
function:
function getLines(minthresh = 8) {
let t = 300,
j = 0;
linesMat = new cv.Mat();
let copy = org_img.clone();
while (t > 0 && j < minthresh) {
try {
cv.HoughLines(tmp, linesMat, 1, Math.PI / 180, t);
j = linesMat.matSize[0]
console.log(`t=${t} j=${j}`, linesMat.matSize);
} catch (err) {
console.log(`error for t=${t}`);
j = 0;
} finally {
t = t - 10;
}
}
console.log('hough lines', linesMat.rows);
let bool = true;
let lines = linesMat.data32F;
let rows = linesMat.rows;
let foundLines = [];
finalLines = [];
for (let i = 0; i < rows; i++) {
let l = [lines[i * 2], lines[i * 2 + 1]];
foundLines.push(l);
}
foundLines.sort((a, b) => a[0] - b[0]);
console.log('filtering lines starts, sorted found lines:', foundLines);
for (let [index, line] of foundLines.entries()) {
let rho = line[0];
let theta = line[1];
let a = Math.cos(theta);
let b = Math.sin(theta);
let x0 = a * rho;
let y0 = b * rho;
let startPoint = {
x: x0 - 1000 * b,
y: y0 + 1000 * a
};
let endPoint = {
x: x0 + 1000 * b,
y: y0 - 1000 * a
};
let color = [random(), random(), random(), 255];
cv.line(copy, startPoint, endPoint, color);
bool = false;
for (let [jindex, linet] of foundLines.slice(index + 1).entries()) {
console.log(`for index=${index} jindex=${jindex+1} linet=${linet} line=${line}`);
bool = false;
if (linet[0] !== line[0]) {
k = [Math.abs(linet[0] - line[0]) < 50, Math.abs(linet[1] - line[1]) < 0.5];
console.log(`k=${k}`);
if (k[0] && k[1]) {
bool = true;
break;
}
}
}
if (bool) {
continue;
}
finalLines.push(line);
console.log(`push for i=${index}`);
console.log(`%c rho=${rho} deg=${theta * (180/Math.PI)}`, `background: rgba(${color[0]}, ${color[1]}, ${color[2]}, 1); color: black`);
}
cv.imshow('op', copy);
}
I'm new to JavaScript, I'm trying to solve leetcode question 37. I need to a create a blank two dimensional array, I initially used the method in the comments; however, it doesn't work correctly, it will change all the value. Then, I used the for loop method to create array and currently it worked correctly. But I still cannot figured out why this will happen, could anyone explain the reason why this will happen, is this because of shallow copy?
var solveSudoku = function (board) {
// let rows = new Array(9).fill(new Array(10).fill(0)),
let rows = new Array(9);
for (let i = 0; i < 9; i++) {
rows[i] = new Array(10).fill(0);
}
let cols = new Array(9);
for (let i = 0; i < 9; i++) {
cols[i] = new Array(10).fill(0);
}
let boxes = new Array(9);
for (let i = 0; i < 9; i++) {
boxes[i] = new Array(10).fill(0);
}
// let cols = new Array(9).fill(new Array(10).fill(0)),
// boxes = new Array(9).fill(new Array(10).fill(0));
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
let c = board[i][j];
if (c !== '.') {
let n = parseInt(c),
bx = Math.floor(j / 3),
by = Math.floor(i / 3);
// 0代表为使用,1为使用过
rows[i][n] = 1;
console.log(i, n)
cols[j][n] = 1;
// box索引
boxes[by * 3 + bx][n] = 1;
}
}
}
fill(board, 0, 0)
function fill(board, x, y) {
// 完成填充条件
if (y === 9) return true;
// 下一个点的坐标
let nx = (x + 1) % 9,
// 判断进入是否下一行
ny = (nx === 0) ? y + 1 : y;
// 如果已经填充,则进入下一个点
if (board[y][x] !== '.') return fill(board, nx, ny);
// 没有被填充过
for (let i = 1; i <= 9; i++) {
let bx = Math.floor(x / 3),
by = Math.floor(y / 3),
box_key = by * 3 + bx;
if (!rows[y][i] && !cols[x][i] && !boxes[box_key][i]) {
rows[y][i] = 1;
cols[x][i] = 1;
boxes[box_key][i] = 1;
board[y][x] = i.toString();
console.log(board[y][x])
// 递归向下一个点求解
if (fill(board, nx, ny)) return true;
// 恢复初始状态
board[y][x] = '.';
boxes[box_key][i] = 0;
rows[y][i] = 0;
cols[x][i] = 0;
}
}
return false;
}
console.log(board);
};
The problem with fill(), at least with object, is that it passes the same object, by reference, to all element of the array. So if you mutate this object, then it will mutate every object of every arrays.
Note that in your case, you are creating a new Array object using it's constructor ( new Array() ) which makes them objects.
const matrix = new Array(5).fill(new Array(5).fill(0));
console.log(matrix);
In the previous snippet, you can see that the values of the other rows, from the second one to the end, are reference to the initial row.
To get around that, you can fill you array with empty values and then use the map() to create unique object for each position in the array.
const matrix = new Array(5).fill().map(function() { return new Array(5).fill(0); });
console.log(matrix);
As you can see in the previous snippet, all the rows are now their unique reference.
This is the reason all of your values were changed.
I've applied this solution to your code. I wasn't able to test it, because I wasn't sure of the initial parameters to pass.
I've also used anonymous function here ( function() { return; } ), but I would success using arrow function ( () => {} ) instead, if you are comfortable with them. It's cleaner.
var solveSudoku = function (board) {
let rows = new Array(9).fill().map(function() { return new Array(10).fill(0); }),
cols = new Array(9).fill().map(function() { return new Array(10).fill(0); }),
boxes = new Array(9).fill().map(function() { return new Array(10).fill(0); });
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
let c = board[i][j];
if (c !== '.') {
let n = parseInt(c),
bx = Math.floor(j / 3),
by = Math.floor(i / 3);
// 0代表为使用,1为使用过
rows[i][n] = 1;
console.log(i, n)
cols[j][n] = 1;
// box索引
boxes[by * 3 + bx][n] = 1;
}
}
}
fill(board, 0, 0)
function fill(board, x, y) {
// 完成填充条件
if (y === 9) return true;
// 下一个点的坐标
let nx = (x + 1) % 9,
// 判断进入是否下一行
ny = (nx === 0) ? y + 1 : y;
// 如果已经填充,则进入下一个点
if (board[y][x] !== '.') return fill(board, nx, ny);
// 没有被填充过
for (let i = 1; i <= 9; i++) {
let bx = Math.floor(x / 3),
by = Math.floor(y / 3),
box_key = by * 3 + bx;
if (!rows[y][i] && !cols[x][i] && !boxes[box_key][i]) {
rows[y][i] = 1;
cols[x][i] = 1;
boxes[box_key][i] = 1;
board[y][x] = i.toString();
console.log(board[y][x])
// 递归向下一个点求解
if (fill(board, nx, ny)) return true;
// 恢复初始状态
board[y][x] = '.';
boxes[box_key][i] = 0;
rows[y][i] = 0;
cols[x][i] = 0;
}
}
return false;
}
console.log(board);
};
I get convergence, nevertheless, the results are never the same when the algorithm is refreshed. This occurs even when the data observations is the same dataset. Can anyone tell me where my methodology is wrong? For the life of me I can't figure out where the process is wrong.
function kmeans2(k, data, canvas, converge) {
this.canvas = jsHS.GetDimensions(canvas);
this.k = k;
this.centroids = []; // Array of centroids
this.centroids2compare = [];
this.data = data;
this.converge = converge;
this.init();
}
kmeans2.prototype.distance = function () {
var dif = 0,
iArray = jsHS.isArray(arguments);
if (iArray) {
if (arguments.length > 2) {
for (var i = 0; i < arguments.length; i+2) {
var p0 = arguments[i],
p1 = arguments[i + 1];
dif += Math.pow(p0[0] - p1[0], 2);
dif += Math.pow(p0[1] - p1[1], 2);
}
}
else {
var pd0 = arguments[0],
pd1 = arguments[1];
dif += Math.pow(pd0[0] - pd1[0], 2);
dif += Math.pow(pd0[1] - pd1[1], 2);
}
}
return Math.sqrt(dif);
};
kmeans2.prototype.Means = function (Array) {
var bin = 0;
[].forEach.call(Array, function(a){
bin += a;
});
return bin / Array.length;
};
kmeans2.prototype.init = function () {
for (var l = 0; l < this.k; l++) {
var dataItem = this.data[Math.floor(Math.random() * this.data.length)];
this.centroids.push(dataItem);
}
for (var i = 0; i < this.centroids.length; i++) {
if (i > 0) {
var distance = this.distance(this.centroids[i], this.centroids[i - 1]);
console.log(distance);
}
}
this.clusterCentroids(); // return centroid center after calculating means.
};
kmeans2.prototype.clusterCentroids = function () {
var points0 = [];
this.centroids2compare = this.centroids;
// Find distances between centroid and observations.
for (var d = 0; d < this.data.length; d++) {
var cinbin = [];
for (var c0 = 0; c0 < this.k; c0++) {
var dis = this.distance(this.centroids[c0], this.data[d]);
cinbin.push({ 'cid': c0, 'distance': dis });
}
var minResult = cinbin.reduce((cid, obj) => {
return obj.distance < cid.distance ? obj : cid;
});
points0.push({ 'id': d, 'datapoint': this.data[d], 'centroid': minResult.cid });
}
// Assign observations their appropriate centroid.
var centroidBin = [];
for (var c = 0; c < this.k; c++) {
var cb = [];
for (var p = 0; p < points0.length; p++) {
if (c === points0[p].centroid) {
cb.push(points0[p]);
}
}
centroidBin.push(cb);
}
// Calculate the mean distance between centroids and its assigned observations.
this.centroids = [];
for (var bin = 0; bin < centroidBin.length; bin++) {
var xAxis = [],
yAxis = [],
cb0 = centroidBin[bin];
[].forEach.call(cb0, function (dp) {
xAxis.push(dp.datapoint[0]);
yAxis.push(dp.datapoint[1]);
});
var xMean = this.Means(xAxis);
var yMean = this.Means(yAxis);
this.centroids.push([xMean, yMean]);
}
// Test for convergence. If stored centroids equal new centroids then convergence is achieved.
if (JSON.stringify(this.centroids2compare) !== JSON.stringify(this.centroids)) {
this.centroids2compare = [];
points0 = [];
this.clusterCentroids();
}
else {
this.converge(centroidBin, this.centroids);
}
};
window['jsHS']['kmeans2'] = kmeans2;
Implementation
var k50 = new jsi.kmeans2(5, Array50, canvas, function (con, centroids) {
var count50 = 0;
var cmark = {
x: 0,
y: 0,
rad:0,
clr: null,
setArc: function () {
ctx.beginPath();
ctx.arc(this.x, this.y, this.rad, 0, Math.PI * 2, true);
ctx.fillStyle = this.clr;
ctx.fill();
}
};
[].forEach.call(centroids, (c) => {
cmark.x = c[0];
cmark.y = c[1];
cmark.clr = '#0B6623';
cmark.rad = 25;
cmark.setArc();
});
});
This example plots the centroids on a canvas area fine enough but when the browser refreshes the centroids change.
I haven't looked much at your code, but I know that the k-means algorithm tends to give different results when you run it several times. This is because it's highly dependent on where the first centroids (which are selected randomly) are located.
The algorithm can find a local minimum and get "stuck" there, and terminate.
There's no guarantee that you will find the global minimum the first time you run it.
I have an integer X and a list of all the factors of X. I want to output the ratio between X and a factor, and for each time set X to that ratio. I want this algorithm to continue till the ratio is bigger than or equal to 1.
For example: X = 36.
All factors (but 1 and 36): 2, 3, 4, 6, 9, 12, 18,
Algorithm: 36 / 2 = 18 --> 18 / 3 = 6 --> 6 / 4 = 1.5 --> 1.5 / 6 < 1 --> Stop
Output: [18, 6, 1.5]. Question:
How do I get this output?
What i have written:
var arr = [];
for (var i = 2; i < X; i++) {
if (X % i == 0) {
arr.push(i);
}
}
var temp = [];
var index = 0;
while (X / arr[index] >= 1) {
index += 1;
X = X / arr[index];
temp.push(X / arr[index]);
}
var arr = [];
var X = 36
for (var i = 2; i < X; i++) {
if (X % i == 0) {
arr.push(i);
}
}
var temp = arr.reduce((acc, item, index) => {
if(!(X/item < 1)){
acc.push(X/item)
X = X/item;
}
return acc;
}, [])
console.log(temp)
You could calculate the first value before you go into the while loop an check the asssigned x. If the value passes the condition, you could push that value to the result array and increment the index and calculate a new value.
function fn(x) {
var array = [], // declare all variable on top
i,
result = [];
for (var i = 2; i < x; i++) {
if (x % i == 0) {
array.push(i);
}
}
i = 0; // prepare index for looping
x /= array[i]; // take a first possible value
while (x >= 1) { // check value
result.push(x); // push value
i++; // increment index
x /= array[i]; // take the next value for checking
}
return result;
}
console.log(fn(36))
A bit shorter with Array#every
function fn(x) {
var array = [], // declare all variable on top
i,
result = [];
for (var i = 2; i < x; i++) {
if (x % i == 0) {
array.push(i);
}
}
array.every(v => (x /= v) >= 1 && result.push(x));
return result;
}
console.log(fn(36))
Your question is a little bit confuse. Is this what you want?
Basically, I update the factor after each iteration (if >= 1) and store into an array the output.
// Generate a range of integers (starting at 2, and we should not including the input)
// get only values divisible by the input (filter)
const generateRange = (input) => {
return Array.from({length: (input - 2)}, (v, k) => k + 2).filter(i => {
return input % i === 0;
})
}
const divideFactors = (input) => {
const list = generateRange(input) // filtered range
let output = []
let factor = input
for (const item of list) {
let ratio = factor / item
if (ratio < 1) { //if ratio < 1, break the loop
break;
}
output.push(ratio) // update output array with new ratio
factor = ratio; // update factor variable with current ratio
}
return output
}
console.log(divideFactors(36))
More info:
Array.from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
For of: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
I need a simple way to divide all the numbers (contained in objects) in an array by a variable in javascript (no jquery or other libraries) :
var divisor = 16;
var array = [{"x":0,"y":16},{"x":16,"y":32},{"x":32,"y":48}];
Expected Result:
[{"x":0,"y":1},{"x":1,"y":2},{"x":2,"y":3}];
Any ideas ?
This should do it for you:
var divisor = 16;
var array = [{"x":0,"y":16},{"x":16,"y":32},{"x":32,"y":48}];
for(var i = 0, length = array.length; i < length; i++){
array[i] = {'x':array[i].x/divisor,'y':array[i].y/divisor};
}
In case you are likely to extend the objects in the future, you might want to do it like this, instead:
for(var i = 0, length = array.length; i < length; i++){
array[i].x /= divisor; // `a[i].x /= d` is shorthand for `a[i].x = a[i].x / d`
array[i].y /= divisor;
}
This has the advantage that it doesn't overwrite array[i], saving possible other properties.
Another solution, using map and a callback:
var divisor = 16;
var array = [{"x":0,"y":16},{"x":16,"y":32},{"x":32,"y":48}];
array = array.map(function(v){
return {x: v.x / divisor, y: v.y / divisor};
});
for (var i = 0; i < array.length; i++) {
array[i]["x"] /= divisor;
array[i]["y"] /= divisor;
}
Deep divide here.
var divideBy = function(object, divider) {
if (typeof(object) == 'number') return object/divider;
for (var i in object) {
if (object.hasOwnProperty(i)) {
object[i] = divideBy(object[i], divider);
}
}
return object;
}
var obj = [{a: 16, b: 32}, {c: 0, d: 48, e: 160}];
console.log(divideBy(obj, 16));
Here it is as a function so you can re-use it. It is not limited to just 2 variables per object.
function divideArray(array, divisor) {
var i = array.length, a, k;
while (i) { // loop over each item in array
a = array[--i];
for (k in a) { // loop over each key in object
if (a.hasOwnProperty(k)) { // ignore inherited keys
a[k] = a[k] / divisor; // calculate
}
}
}
return array;
}
// use with your example
var divisor = 16;
var array = [{"x":0,"y":16},{"x":16,"y":32},{"x":32,"y":48}];
array = divideArray(array, divisor);
Try this
var divisor = 16;
var array = [{"x":0,"y":16},{"x":16,"y":32},{"x":32,"y":48}];
var i=0;
for(i=0;i<array.length;i++)
{
array[i]["y"]=array[i]["y"]/divisor;
array[i]["x"]=array[i]["x"]/divisor;
}
var divisor = 16;
var array = [{"x":0,"y":16},{"x":16,"y":32},{"x":32,"y":48}];
var i=0;
for(i=0;i<array.length;i++)
{
array[i]["y"]=array[i]["y"]/divisor;
array[i]["x"]=array[i]["x"]/divisor;
}