I'm trying to use Dijkstra's Algorithm to path find every position of a maze back to a specific point.
I found a JavaScript version of Dijkstra's Algorithm here:
https://github.com/bm1362/dijkstra-js/blob/master/nodes.js
(Thank you bm1362!)
The way I've approached creating the maze graph is as follows:
// the maze
var maze =
[[1, 1, 1, 1],
[1, 0, 0, 0],
[1, 0, 0, 0],
[1, 1, 1, 1]];
maze2 = [];
var i = 0;
var mazeSize = 30;
for (var x = 0; x < maze[0].length; x++) {
for (var y = 0; y < maze[0].length; y++) {
if (maze[x][y] == 1) {
nodes.push(new node);
nodes[i].setPos((x) * (maze[0].length + 100), (y) * ((maze[0].length + 100)))
nodes[i].tmppos = [x, y];
nodes[i].id = i;
maze2[x + ',' + y] = nodes[i];
i++;
}
}
}
//sort nodes in order of x position
var sortedNodes = quickSort(nodes);
//var sortedNodes = nodes;
for (var i = 0; i < sortedNodes.length; i++) {
sortedNodes[i].number = i;
var n1 = sortedNodes[i];
var up = {}, down = {}, left = {}, right = {};
var pos = [];
up.x = n1.tmppos[0];
up.y = n1.tmppos[1] - 1;
pos.push(up);
down.x = n1.tmppos[0];
down.y = n1.tmppos[1] + 1;
pos.push(down);
left.x = n1.tmppos[0] - 1;
left.y = n1.tmppos[1];
pos.push(left);
right.x = n1.tmppos[0] + 1;
right.y = n1.tmppos[1];
pos.push(right);
for (var m = 0; m < pos.length; m++) {
if (maze[pos[m].x] != undefined && maze[pos[m].x][pos[m].y] != undefined && maze[pos[m].x][pos[m].y] == 1) {
var n2 = maze2[pos[m].x + ',' + pos[m].y];
var dist = calcDist(n1, n2);
sortedNodes[i].addConnection(n2);
connections.push({
a: n1,
b: n2,
dist: dist
})
}
}
}
The issue that I'm having is even though all the nodes do seem to have a connection, when the algorithm runs, some of the nodes do not get a parent set. But I've tried many different ways and I still cannot get it to set all the parents.
I've created a JS fiddle here: http://jsfiddle.net/XcdCr/3/
Any help would be greatly appreciated.
Related
I am developing a Rubik cube app for fitbit versa and I run into the problem of removing duplicates from arrays as I get a NaN error when combining the arrays once the duplicates have been removed from the end of the list and it only happens when I splice at the end of the array and I cant figure out the reason why this isnt working
function getScramble(number_of_moves, faces, modifiers, scramble_faces, scramble_modifiers, scramble) {
for (var i = 0; i < number_of_moves; i++) {
var sample = faces[Math.floor(Math.random() * faces.length)];
var mod = modifiers[Math.floor(Math.random() * modifiers.length)];
scramble_faces[i] = sample;
scramble_modifiers[i] = mod;
if (scramble_faces[i] == scramble_faces[i - 1]) {
scramble_faces[i] = faces[Math.floor(Math.random() * faces.length)];
}
}
removeDuplicates(scramble_faces, scramble_modifiers)
for (var i = 0; i < number_of_moves - 2; i++) {
scramble[i] = scramble_faces[i] + scramble_modifiers[i]
}
console.log(scramble);
let demotext = document.getElementById("demotext");
demotext.text = scramble;
scramble = [];
scramble_faces = [];
scramble_modifiers = [];
}
function threebythree() {
var faces = ["U", "D", "L", "R", "F", "B"];
var modifiers = ["", "'", "2"];
var scramble_faces = [];
var scramble_modifiers = [];
var scramble = [];
var number_of_moves = 22;
let Title1 = document.getElementById("title");
Title1.text = "3x3"
getScramble(number_of_moves, faces, modifiers, scramble_faces, scramble_modifiers, scramble, Title1)
}
function removeDuplicates(arr, arr2, number_of_moves) {
var t = 0;
var new_arr = arr;
var new_arr2 = arr2;
for (var i = new_arr.length - 1; i >= 0; i--) {
if (new_arr[i] === new_arr[i - 1]) {
new_arr.splice(i, 1);
new_arr2.splice(i, 1);
}
}
arr = new_arr;
arr2 = new_arr2;
new_arr = [];
new_arr2 = [];
new_arr.pop();
new_arr2.pop();
console.log(arr);
console.log(arr2);
}
The lengths of scramble_faces and scramble_modifiers is initially number_of_moves. But after you remove duplicates from them, it can be shorter. But you still use number_of_moves in the limit in the next for loop. So when you try to add the elements that no longer exist you get undefined. undefined + undefined == NaN.
You should use the length of one of the arrays instead:
function getScramble(number_of_moves, faces, modifiers, scramble_faces, scramble_modifiers, scramble) {
for (var i = 0; i < number_of_moves; i++) {
var sample = faces[Math.floor(Math.random() * faces.length)];
var mod = modifiers[Math.floor(Math.random() * modifiers.length)];
scramble_faces[i] = sample;
scramble_modifiers[i] = mod;
if (scramble_faces[i] == scramble_faces[i - 1]) {
scramble_faces[i] = faces[Math.floor(Math.random() * faces.length)];
}
}
removeDuplicates(scramble_faces, scramble_modifiers)
for (var i = 0; i < scramble_faces.length - 2; i++) {
scramble[i] = scramble_faces[i] + scramble_modifiers[i]
}
console.log(scramble);
let demotext = document.getElementById("demotext");
demotext.text = scramble;
scramble = [];
scramble_faces = [];
scramble_modifiers = [];
}
Getting an error message for the below code that works to get Values from several cells in my order entry tab named POTemplate and log them in my POHistory tab the serves to compile a list of all order detail entries. As the debugger gets to the bottom of the below code, I get an error message stating: "Cannot Read Property 0.0 from Undefined"
function submit() {
var app = SpreadsheetApp;
var tplSheet = app.getActiveSpreadsheet().getSheetByName("POTemplate");
var tplFRow = 22, tplLRow = tplSheet.getLastRow();
var tplRowsNum = tplLRow - tplFRow + 1;
var tplFCol = 1, tplLCol = 16;
var tplColsNum = tplLCol - tplFCol + 1;
var rangeData = tplSheet.getRange(22, 1, 5, 15).getValues();
var colIndexes = [0, 3, 10, 12, 15];
var fData = filterByIndexes(rangeData, colIndexes);
var target = "POHistory";
var targetSheet = app.getActiveSpreadsheet().getSheetByName(target);
var tgtRow = targetSheet.getLastRow() + 1;
var tgtRowsNum = fData.length - tgtRow + 1;
var tgtCol = 1;
var tgtColsNum = fData[0].length - 1 + 1;
targetSheet.getRange(tgtRow, tgtCol, tgtRowsNum,
tgtColsNum).setValues(fData);
}
function filterByIndexes(twoDArr, indexArr) {
var fData = [];
twoDArr = twoDArr.transpose();
for(var i = 0; i < indexArr.length; i++) {
fData.push(twoDArr[indexArr[i]]);
}
return fData.transpose();
}
Array.prototype.transpose = function() {
var a = this,
w = a.length ? a.length : 0,
h = a[0] instanceof Array ? a[0].length : 0;
if (h === 0 || w === 0) {return [];}
var i, j, t = [];
for (i = 0; i < h; i++) {
t[i] = [];
for (j = 0; j < w; j++) {
t[i][j] = a[j][i];
}
}
return t;
}
I need to do a simple diagonal matrix in JS, which should look like this one:
[
[4, 7, 9],
[2, 5, 8],
[1, 3, 6]
]
My idea is to use a 2-d array and two loops, but the result I get is an empty array.You'll see below what my code looks like, but obviously I have a problem with the values.
function fillMatrix(n) {
var matrix = [];
var rows = 0;
var cols = 0;
var startCount = 1;
for (var i = (n - 1); i >= 0; i--) {
rows = i;
cols = 0;
matrix[rows] = [];
while (rows < n && cols < n) {
matrix[rows++][cols++] = startCount++;
}
for (var j = 0; j < n; j++) {
rows = j;
cols = 0;
matrix[rows] = [];
while (rows < n && cols < n) {
matrix[cols++][cols++] = startCount++;
}
}
}
return matrix;
}
n = +prompt();
console.log(fillMatrix(n));
The logic for creating a diagonal matrix can be greatly simplified if one looks at the patterns between rows. (I won't go through all of the math here, but feel free to ask me questions in the comments about any specific sections you find confusing.)
Take, for example, the 4x4 diagonal matrix:
Successive differences between elements in a row form the pattern below:
I might still work on shortening the method below, but right now it works and is fairly concise.
Demo:
function diagonalMatrix (n) {
var matrix = [], row
for (var i = n; i > 0; i--) {
var x = i*(i-1)/2 + 1, dx = i
matrix.push(row = [])
for (var j = n; j > 0; j--) {
row.push(x)
x += (i < j ? ++dx : dx--)
}
}
return matrix
}
var matrix = diagonalMatrix(+prompt('Diagonal Matrix Order:'))
console.log(beautify(matrix))
console.log(matrix)
// For visualization purposes
function beautify (matrix) {
return matrix.map(function (e) {
return e.join('\t')
}).join('\n\n\n\n')
}
.as-console-wrapper { min-height: 100vh; }
I'm trying to implement Knight's Tour algorithm from the book "Algorithms and Data Structures" by N. Wirth. The original version is written in Oberon:
https://drive.google.com/file/d/0B7KbTu852Hi3cG5jYUVDX3Z4Yjg/view?usp=sharing
The problem is that I receive an error "Cannot set property '-1' of undefined" at line h[u][v] = i;
At step 36 algorithm goes to dead-end of the board. Little help?
var n = 8; // size of the board
var nsqr = n * n;
// board matrix
var h = [];
for (var i = 0; i < n; i++) {
h[i] = [];
}
var dx = [2, 1, -1, -2, -2, -1, 1, 2]; // coordinates difference along X, possible 8 moves
var dy = [1, 2, 2, 1, -1, -2, -2, -1]; // coordinates difference along Y, possible 8 moves
// knight's tour
function knightsTour(xin, yin) {
clear();
h[xin][yin] = 1; // initial position and step number
var done = false;
tryNextMove(xin, yin, 1, done);
}
// clear
function clear() {
for (var i = 0; i < n; i++) {
for (var j = 0; j < n; j++) {
h[i][j] = 0;
}
}
}
// try next move
function tryNextMove(x, y, i, done) {
var eos; // end of steps, bool
var u, v; // new step coordinates
var k; // new step index
function next(eos) {
do {
k++;
if (k < 8) {
u = x + dx[k];
v = y + dy[k];
}
} while (k < 8 && (u < 0 || u >= n || v < 0 || v >= n || h[u][v] != 0));
eos = (k == 8);
}
function first(eos) {
eos = false;
k = -1;
next(eos);
}
if (i < nsqr) {
first(eos);
while (!eos && !canBeDone(u, v, i+1)) {
next(eos);
}
done = !eos;
} else {
done = true;
}
}
// can tour be done
function canBeDone(u, v, i) {
var done = false; // bool
h[u][v] = i; // ERROR here
tryNextMove(u, v, i, done);
if (!done) { h[u][v] = 0; }
return done;
}
knightsTour(3, 1);
console.log(h);
This version works for n = 4...9:
function knightsTour(x0, y0, size = 8) {
var done = false;
var h = []; // chess board matrix
for (var i = 0; i < size; i++) {
h[i] = [];
}
var nsqr = size * size;
// initializing the board
for (var i = 0; i < size; i++) {
for (var j = 0; j < size; j++) {
h[i][j] = 0;
}
}
// coordinates difference along X and Y, possible 8 moves
var dx = [2, 1, -1, -2, -2, -1, 1, 2];
var dy = [1, 2, 2, 1, -1, -2, -2, -1];
h[x0][y0] = 1; // initial position and step number
// check if move can be done
function canBeDone(u, v, i) {
h[u][v] = i;
done = tryNextMove(u, v, i);
if (!done) {
h[u][v] = 0;
}
return done;
}
// try next move
function tryNextMove(x, y, i) {
var done;
// u, v - new step coordinates; k - new step index; eos - end of steps, bool
var env = {"done": false, "eos": false, "u": x, "v": y, "k": -1};
function next() {
x = env.u;
y = env.v;
while (env.k < 8) {
env.k += 1;
if (env.k < 8) {
env.u = x + dx[env.k];
env.v = y + dy[env.k];
}
if ((env.u >= 0 && env.u < size) && (env.v >= 0 && env.v < size) && h[env.u][env.v] == 0) {
break;
}
}
env.eos = (env.k == 8);
}
if (i < nsqr) {
next();
while (!env.eos && !canBeDone(env.u, env.v, i+1)) {
next();
}
done = !env.eos;
} else {
done = true;
}
return done;
}
tryNextMove(x0, y0, 1);
//console.log(h);
return h;
}
The first thing to check is how you're scoping the u and v.
Check this code.
In first() and next() you were giving u and v as parameters. But this means that the function has a different copy of u and v from the one you're referencing in canBeDone.
Now the problem is that the algorithm fails when u=9. This is a starting point for further debugging.
var n = 8; // size of the board
var nsqr = n * n;
// board matrix
var h = [];
for (var i = 0; i < n; i++) {
h[i] = [];
}
var dx = [2, 1, -1, -2, -2, -1, 1, 2]; // coordinates difference along X, possible 8 moves
var dy = [1, 2, 2, 1, -1, -2, -2, -1]; // coordinates difference along Y, possible 8 moves
// knight's tour
function knightsTour(xin, yin) {
clear();
h[xin][yin] = 1; // initial position and step number
var done = false;
tryNextMove(xin, yin, 1, done);
}
// clear
function clear() {
for (var i = 0; i < n; i++) {
for (var j = 0; j < n; j++) {
h[i][j] = 0;
}
}
}
// try next move
function tryNextMove(x, y, i, done) {
var eos; // end of steps, bool
var u, v; // new step coordinates
var k; // new step index
function next(eos) {
do {
k++;
if (k < 8) {
uNew = x + dx[k];
vNew = y + dy[k];
}
} while (k < 8 || (u < 0 && u >= n && v < 0 && v >= n && (h[u][v] != 0)));
eos = (k == 8);
}
function first(eos) {
eos = false;
k = -1;
next(eos, u, v);
}
if (i < nsqr) {
first(eos);
while (!eos && !canBeDone(u, v, i+1)) {
next(eos);
}
done = !eos;
} else {
done = true;
}
}
// can tour be done
function canBeDone(u, v, i) {
var done = false; // bool
h[u][v] = i; // ERROR here
tryNextMove(u, v, i, done);
if (!done) { h[u][v] = 0; }
return done;
}
knightsTour(3, 1);
console.log(h);
I have a random generator from 1 to 10 that produces non repeating values
I am trying to get the previous value.
So if current is 5 and then 8
Previous 8 and next is 9, etc
This is my code:
var randomNumbers = [];
var numRandoms = 11;
var myVar = setInterval(randomUnique1to10, 5000);
function randomUnique1to10() {
// refill the array if needed
if (!randomNumbers.length) {
for (var i = 1; i < numRandoms; i++) {
randomNumbers.push(i);
}
}
var index = Math.floor(Math.random() * randomNumbers.length);
var val = randomNumbers[index];
if (i === 1) { // i would become 0
i = randomNumbers.length; // so put it at the other end of the array
}
i = i - 1; // decrease by one
previous = randomNumbers[i]; // give us back the item of where we are now
randomNumbers.splice(index, 1);
Thank you
This is totally what you're looking for. Hope it helps!.
var randomNumbers = [];
var numRandoms = 11;
var myVar = setInterval(randomUnique1to10, 1000);
shuffle = function(o){
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
var finalArray = shuffle([1, 2, 3, 4,5,6,7,8,9,10]);
function randomUnique1to10() {
// refill the array if needed
if (!randomNumbers.length) {
for (var i = 1, l = 11; i < l; i++) { }
}
// var finalArray = shuffle(randomNumbers);
document.write(finalArray + "<br/>");
randomNumbers = finalArray;
var index = Math.floor(Math.random() * randomNumbers.length);
var val = randomNumbers[index];
if (i === 1) { // i would become 0
i = randomNumbers.length; // so put it at the other end of the array
}
x = index-1; // decrease by one
current = randomNumbers[randomNumbers.length - 1]; // give us back the item of where we are now
previous = randomNumbers[randomNumbers.length - 2];
if(previous === undefined)
{
previous = "n/a";
}
randomNumbers.pop();
if(randomNumbers.length <= 0){
finalArray = shuffle([1, 2, 3, 4,5,6,7,8,9,10]);
}
document.write("Current >> " + current + " and previous = " +previous + "<br/>")
}
try this:
var randomNumbers = [];
var numRandoms = 11;
var myVar = setInterval(randomUnique1to10, 5000);
var x;
function randomUnique1to10() {
// refill the array if needed
if (!randomNumbers.length) {
for (var i = 1; i < numRandoms; i++) {
randomNumbers.push(i);
}
}
var index = Math.floor(Math.random() * randomNumbers.length);
var val = randomNumbers[index];
if (i === 1) { // i would become 0
i = randomNumbers.length; // so put it at the other end of the array
}
x = index-1; // decrease by one
previous = randomNumbers[x]; // give us back the item of where we are now
var res = randomNumbers.splice(index, 1);
console.log("result: "+res);
console.log("prev : "+previous);
console.log("Rand : "+randomNumbers);
}
NOTE:
this code have, one problem, if res = min(array) then prev will become unidentify
The question lack a bit of clarity. From the question what I understood is,
The values in the array are non repeating
You have a value at variable current and you want to find the previous value of the current which is stored in the array
And I will answer from what I understood. Using indexOf() gives you the index of current element from the array and you just need to subtract 1 from it to get the previous.
var array = [1, 9, 2, 8, 3, 7, 4, 6, 5];
var current = 8;
var currentIndex = array.indexOf(current);
var previous = currentIndex !== 0 ? array[currentIndex-1] : 'N/A';
document.write('Previous Value: ', previous)