I implemented Jarvis march in javascript and then submitted it, turns out in some cases it goes into an infinite loop. I tried changing almost everything and it seems like the code keeps on going into an infinite loop just for a few test cases.
This is my current code, the last for loop is to get all the points lying on the lines made by the convex hull points.
function convexHull(points, n)
{
// There must be at least 3 points
if (n < 3) return;
// Find the leftmost point
let l = 0;
let hull = [];
for (let i = 1; i < n; i++)
{
if (points[i].x < points[l].x)
l = i;
else if (points[i].x == points[l].x && points[i].y < points[l].y)
l = i;
}
// Start from leftmost point, keep moving
// counterclockwise until reach the start point
// again. This loop runs O(h) times where h is
// number of points in result or output.
let p = l, q;
do
{
// Add current point to result
hull.push(points[p]);
newhull.push(points[p]);
// Search for a point 'q' such that
// orientation(p, q, x) is counterclockwise
// for all points 'x'. The idea is to keep
// track of last visited most counterclock-
// wise point in q. If any point 'i' is more
// counterclock-wise than q, then update q.
q = (p + 1) % n;
for (let i = 0; i < n; i++)
{
// If i is more counterclockwise than
// current q, then update q
if ((orientation(points[p], points[i], points[q])
== 2))
q = i;
if(p != i && orientation(points[p], points[i], points[q]) == 0
&& onSegment(points[p], points[q], points[i])) {
q = i;
}
}
p = q;
}while (p != l); // While we don't come to first point
for(let i = 0; i < hull.length; i++) {
if(i + 1 < hull.length) {
for (let j = 0; j < points.length; j++) {
if(orientation(hull[i], points[j], hull[i+1]) == 0) {
newhull.push(points[j]);
points.splice(j, 1);
j--; }
}
}
else if(i + 1 == hull.length) {
for (let j = 0; j < points.length; j++) {
if(orientation(hull[i], points[j], hull[i+1]) == 0) {
newhull.push(points[j]);
points.splice(j, 1);
j--;
}
}
}
}
}
Any help pointing out how I could improve this or get out of an infinite loop would be much appreciated.
Related
I am creating a basic airplane game, and attempting to get the enemy planes to move in a rectangular formation. I am able to get them to move down to the correct space on the screen, but when I add the code to move left, up or down the screen goes blank except for my background. I used 5 differenct functions here, one for each direction, looping to the next function in line at the end. Any help to get this moving correctly would be amazing!
function moveEnemies(){
moveEnemiesDown();
}
function moveEnemiesDown(){
for(var idx = 0 ; idx < enemies.length; idx++)
if(enemies[idx].top <= 360){ //down
enemies[idx].top = enemies[idx].top + 2
};
moveEnemiesleft();
}
function moveEnemiesleft(){
for( var idx = 0 ; ide < enemies.length; idx ++)
if(enemies[idx].left > 20){ //left
enemies[idx].left = enemies[idx].left - 2
};
moveEnemiesUp();
}
function moveEnemiesUp(){
for( var idx = 0 ; ide < enemies.length; idx ++)
if(enemies[idx].top > 10){ //up
enemies[idx].top = enemies[idx].top - 2
};
moveEnemiesRight();
}
function moveEnemiesRight(){
for( var idx = 0 ; ide < enemies.length; idx ++)
if(enemies[idx].left < 800 ){ //right
enemies[idx].left = enemies[idx].left + 2
};
moveEnemiesDown();
}
What is happening here is you calling all the methods in an endless loop. Check this out:
function moveEnemies(){
moveEnemiesDown(); // you begin calling here, its fine
}
function moveEnemiesDown(){
for(var idx = 0 ; idx < enemies.length; idx++) {
if(enemies[idx].top <= 360){ //down "safety hatch", its okay
enemies[idx].top = enemies[idx].top + 2
}
};
moveEnemiesleft(); // invoke next step
}
function moveEnemiesleft(){
for( var idx = 0 ; ide < enemies.length; idx ++) {
if(enemies[idx].left > 20) { //left, ok
enemies[idx].left = enemies[idx].left - 2
};
moveEnemiesUp(); // get to the next moves
}
}
function moveEnemiesUp(){
for( var idx = 0 ; ide < enemies.length; idx ++) {
if(enemies[idx].top > 10){ //up, ok
enemies[idx].top = enemies[idx].top - 2
};
moveEnemiesRight(); // move right
}
}
function moveEnemiesRight(){
for( var idx = 0 ; ide < enemies.length; idx ++) {
if(enemies[idx].left < 800 ){ //right, ok
enemies[idx].left = enemies[idx].left + 2
};
moveEnemiesDown(); // move down, but then your airplanes don't move
// since they are already enemies[idx].top > 360 at some point,
// and all the functions keep looping without moving your airplanes
}
}
Aside from that, you probably have missed a bunch of { and } here and there. To fix your problem, add this statement to moveEnemiesDown:
function moveEnemiesDown(){
if (enemies[0].top > 360) return; // this will end the function sooner, and won't make your code stuck
for(var idx = 0 ; idx < enemies.length; idx++) {
if(enemies[idx].top <= 360){ //down
enemies[idx].top = enemies[idx].top + 2
}
};
moveEnemiesleft(); // invoke next step
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I understand the "Depth-First" maze geerating algorithm but I need a little help implementing it with Javascript.
Maze Generation at Rosetta Code contains many implementations to generate and show a maze, using the simple Depth-first search algorithm:
Code in JavaScript:
function maze(x,y) {
var n=x*y-1;
if (n<0) {alert("illegal maze dimensions");return;}
var horiz=[]; for (var j= 0; j<x+1; j++) horiz[j]= [];
var verti=[]; for (var j= 0; j<y+1; j++) verti[j]= [];
var here= [Math.floor(Math.random()*x), Math.floor(Math.random()*y)];
var path= [here];
var unvisited= [];
for (var j= 0; j<x+2; j++) {
unvisited[j]= [];
for (var k= 0; k<y+1; k++)
unvisited[j].push(j>0 && j<x+1 && k>0 && (j != here[0]+1 || k != here[1]+1));
}
while (0<n) {
var potential= [[here[0]+1, here[1]], [here[0],here[1]+1],
[here[0]-1, here[1]], [here[0],here[1]-1]];
var neighbors= [];
for (var j= 0; j < 4; j++)
if (unvisited[potential[j][0]+1][potential[j][1]+1])
neighbors.push(potential[j]);
if (neighbors.length) {
n= n-1;
next= neighbors[Math.floor(Math.random()*neighbors.length)];
unvisited[next[0]+1][next[1]+1]= false;
if (next[0] == here[0])
horiz[next[0]][(next[1]+here[1]-1)/2]= true;
else
verti[(next[0]+here[0]-1)/2][next[1]]= true;
path.push(here= next);
} else
here= path.pop();
}
return ({x: x, y: y, horiz: horiz, verti: verti});
}
function display(m) {
var text= [];
for (var j= 0; j<m.x*2+1; j++) {
var line= [];
if (0 == j%2)
for (var k=0; k<m.y*4+1; k++)
if (0 == k%4)
line[k]= '+';
else
if (j>0 && m.verti[j/2-1][Math.floor(k/4)])
line[k]= ' ';
else
line[k]= '-';
else
for (var k=0; k<m.y*4+1; k++)
if (0 == k%4)
if (k>0 && m.horiz[(j-1)/2][k/4-1])
line[k]= ' ';
else
line[k]= '|';
else
line[k]= ' ';
if (0 == j) line[1]= line[2]= line[3]= ' ';
if (m.x*2-1 == j) line[4*m.y]= ' ';
text.push(line.join('')+'\r\n');
}
return text.join('');
}
Code in Java:
public int[][] generateMaze() {
int[][] maze = new int[height][width];
// Initialize
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
maze[i][j] = 1;
Random rand = new Random();
// r for row、c for column
// Generate random r
int r = rand.nextInt(height);
while (r % 2 == 0) {
r = rand.nextInt(height);
}
// Generate random c
int c = rand.nextInt(width);
while (c % 2 == 0) {
c = rand.nextInt(width);
}
// Starting cell
maze[r][c] = 0;
// Allocate the maze with recursive method
recursion(r, c);
return maze;
}
public void recursion(int r, int c) {
// 4 random directions
int[] randDirs = generateRandomDirections();
// Examine each direction
for (int i = 0; i < randDirs.length; i++) {
switch(randDirs[i]){
case 1: // Up
// Whether 2 cells up is out or not
if (r - 2 <= 0)
continue;
if (maze[r - 2][c] != 0) {
maze[r-2][c] = 0;
maze[r-1][c] = 0;
recursion(r - 2, c);
}
break;
case 2: // Right
// Whether 2 cells to the right is out or not
if (c + 2 >= width - 1)
continue;
if (maze[r][c + 2] != 0) {
maze[r][c + 2] = 0;
maze[r][c + 1] = 0;
recursion(r, c + 2);
}
break;
case 3: // Down
// Whether 2 cells down is out or not
if (r + 2 >= height - 1)
continue;
if (maze[r + 2][c] != 0) {
maze[r+2][c] = 0;
maze[r+1][c] = 0;
recursion(r + 2, c);
}
break;
case 4: // Left
// Whether 2 cells to the left is out or not
if (c - 2 <= 0)
continue;
if (maze[r][c - 2] != 0) {
maze[r][c - 2] = 0;
maze[r][c - 1] = 0;
recursion(r, c - 2);
}
break;
}
}
}
/**
* Generate an array with random directions 1-4
* #return Array containing 4 directions in random order
*/
public Integer[] generateRandomDirections() {
ArrayList<Integer> randoms = new ArrayList<Integer>();
for (int i = 0; i < 4; i++)
randoms.add(i + 1);
Collections.shuffle(randoms);
return randoms.toArray(new Integer[4]);
}
Source, demo and some more explanations
On a 2-dimensional grid, there are 4 types of squares:
1 represents the starting square. There is exactly one starting square.
2 represents the ending square. There is exactly one ending square.
0 represents empty squares we can walk over.
-1 represents obstacles that we cannot walk over.
Return the number of 4-directional walks from the starting square to the ending square, that walk over every non-obstacle square exactly once.
source:力扣(LeetCode)
link:https://leetcode-cn.com/problems/unique-paths-iii
i'm trying to use backtrack pattern to solve this problem
here is my code
/**
* #param {number[][]} grid
* #return {number}
*/
var uniquePathsIII = function(grid) {
let m = grid.length,
n = grid[0].length;
let start, targetIndex1,targetIndex2;
let res = 0;
let zero_counts = 0;
for(let i = 0; i < m; i++){
for(let j = 0; j < n; j++){
if(grid[i][j] == 1){
start = [i,j]
}
else if(grid[i][j] == 0){
zero_counts += 1;
}
else if(grid[i][j] == 2){
targetIndex1 = i;
targetIndex2 = j;
}
}
}
const backtrace = (i, j, zero_count) => {
if( i < 0 || i >= m ||
j < 0 || j >= n ||
grid[i][j] == -1 || zero_count < 0)
{
return;
}
if(i == targetIndex1 && j == targetIndex2 ){
if(zero_count == 0)
{
console.log("yes")
res += 1;
}
return
}
grid[i][j] = -1;
backtrace(i+1, j, zero_count - 1)
backtrace(i-1, j, zero_count - 1)
backtrace(i, j+1, zero_count - 1)
backtrace(i, j-1, zero_count - 1)
grid[i][j] = 0;
}
backtrace(start[0], start[1], zero_counts);
return res;
};
test sample:
[[1,0,0,0],[0,0,0,0],[0,0,2,-1]]
expect result:
2
acutal result:
0
Perhaps a simpler solution is to use Depth First Search to solve Unique Paths III, as shown here.
The concept is that you take a point and then traverse in all directions until you hit an obstacle.
The guts are as follows:
int totalPaths = dfs(grid, x+1, y, zero) +
dfs(grid, x, y+1, zero) +
dfs(grid, x-1, y, zero) +
dfs(grid, x, y-1, zero);
I'm learning JavaScript at the moment and have an exercise to solve. The exercise is given bellow:
Output prime numbers
An integer number greater than 1 is called a prime. if it cannot be divided without a
remainder by anything except 1 and itself.
In other words, n > 1 is a prime if it can’t be evenly divided by anything except 1 and n .
For example, 5 is a prime, because it cannot be divided without a remainder by 2 , 3 and 4 .
Write the code which outputs prime numbers in the interval from 2 to n .
For n = 10 the result will be 2,3,5,7 .
P.S. The code should work for any n , not be hard-tuned for any fixed value.
Now i try to solve it this way.
let n = 20;
outer:
for (let i = 2; i < n; i++) {
for (let j = 1; j < n; j++) {
while (j>1 && j<i) {
if (i%j == 0 ) {
continue outer
}
}
}
console.log(i);
}
but it show wrong output
now i also can solve it in this way
let n = 20;
let result = 0;
outer:
for (let i = 2; i < n; i++) {
for (let j = 2; j < i; j++) {
if (i%j == 0) {
continue outer
}
}
console.log(i)
}
Now I ask for your help to know that exactly in where I did mistake in 1st Salutation .
The problem is that if if (i%j == 0 ) is false you remain in the while without changing the variables so you are infinite stuck there.
You could add another label for the inner for and either go to the one or the other
let n = 20;
outer: for (let i = 2; i < n; i++) {
inner: for (let j = 1; j < n; j++) {
while (j>1 && j<i) {
if (i%j == 0 ) {
continue outer;
} else {
continue inner;
}
}
}
console.log(i);
}
I have an issue with a recursive algorithm, that solves the problem of finding the happy numbers.
Here is the code:
function TestingFunction(number){
sumNumberContainer = new Array(0);
CheckIfNumberIsHappy(number);
}
function CheckIfNumberIsHappy(number){
var sumOfTheNumbers = 0;
for (var i = 0; i < number.length; i++) {
sumOfTheNumbers += Math.pow(parseInt(number[i]), 2);
}
console.log(sumOfTheNumbers);
if(sumOfTheNumbers == 1){
return CheckIfNumberIsHappy(sumOfTheNumbers.toString());
//return true;
} else {
sumNumberContainer.push(sumOfTheNumbers);
if(sumNumberContainer.length > 1){
for (var i = 0; i < sumNumberContainer.length - 1; i++) {
for (var j = i + 1; j < sumNumberContainer.length; j++) {
if(sumNumberContainer[i] == sumNumberContainer[j]){
return CheckIfNumberIsHappy(sumOfTheNumbers.toString());
//return false;
}
}
}
}
CheckIfNumberIsHappy(sumOfTheNumbers.toString());
}
}
Algorithm is working ALMOST fine. I've tested it out by calling function with different numbers, and console was displaying correct results. The problem is that I almost can't get any value from the function. There are only few cases in which I can get any value: If the number is build out of ,,0", and ,,1", for example 1000.
Because of that, I figured out, that I have problem with returning any value when the function is calling itself again.
Now I ended up with 2 results:
Returning the
return CheckIfNumberIsHappy(sumOfTheNumbers.toString());
which is giving an infinity looped number. For example when the number is happy, the function is printing in the console number one again and again...
Returning the
//return true
or
//return false
which gives me an undefined value
I'm a little bit in check by this problem, and I'm begging you guys for help.
I would take a step back and reexamine your problem with recursion in mind. The first thing you should think about with recursion is your edge cases — when can you just return a value without recursing. For happy numbers, that's the easy case where the sum of squares === 1 and the harder case where there's a cycle. So test for those and return appropriately. Only after that do you need to recurse. It can then be pretty simple:
function sumSq(num) {
/* simple helper for sums of squares */
return num.toString().split('').reduce((a, c) => c * c + a, 0)
}
function isHappy(n, seen = []) {
/* seen array keeps track of previous values so we can detect cycle */
let ss = sumSq(n)
// two edge cases -- just return
if (ss === 1) return true
if (seen.includes(ss)) return false
// not an edge case, save the value to seen, and recurse.
seen.push(ss)
return isHappy(ss, seen)
}
console.log(isHappy(23))
console.log(isHappy(22))
console.log(isHappy(7839))
Here's a simplified approach to the problem
const digits = x =>
x < 10
? [ x ]
: [ ...digits (x / 10 >> 0), x % 10 ]
const sumSquares = xs =>
xs.reduce ((acc, x) => acc + x * x, 0)
const isHappy = (x, seen = new Set) =>
x === 1
? true
: seen.has (x)
? false
: isHappy ( sumSquares (digits (x))
, seen.add (x)
)
for (let n = 1; n < 100; n = n + 1)
if (isHappy (n))
console.log ("happy", n)
// happy 1
// happy 7
// happy 10
// ...
// happy 97
The program above could be improved by using a technique called memoization
Your code is almost correct. You just forgot to return the result of the recursive call:
function TestingFunction(number){
sumNumberContainer = new Array(0);
if (CheckIfNumberIsHappy(number))
console.log(number);
}
function CheckIfNumberIsHappy(number){
var sumOfTheNumbers = 0;
for (var i = 0; i < number.length; i++) {
sumOfTheNumbers += Math.pow(parseInt(number[i]), 2);
}
if(sumOfTheNumbers == 1){
return true;
} else {
sumNumberContainer.push(sumOfTheNumbers);
if(sumNumberContainer.length > 1){
for (var i = 0; i < sumNumberContainer.length - 1; i++) {
for (var j = i + 1; j < sumNumberContainer.length; j++) {
if(sumNumberContainer[i] == sumNumberContainer[j]){
return false;
}
}
}
}
return CheckIfNumberIsHappy(sumOfTheNumbers.toString());
}
}
for (let i=0; i<100; ++i)
TestingFunction(i.toString()); // 1 7 10 13 ... 91 94 97
I've got the solution, which was given to me in the comments, by the user: Mark_M.
I just had to use my previous
return true / return false
also I had to return the recursive statement in the function, and return the value of the CheckIfTheNumberIsHappy function, which was called in TestingFunction.
The working code:
function TestingFunction(number){
sumNumberContainer = new Array(0);
return CheckIfNumberIsHappy(number);
}
function CheckIfNumberIsHappy(number){
var sumOfTheNumbers = 0;
for (var i = 0; i < number.length; i++) {
sumOfTheNumbers += Math.pow(parseInt(number[i]), 2);
}
console.log(sumOfTheNumbers);
if(sumOfTheNumbers == 1){
return true;
} else {
sumNumberContainer.push(sumOfTheNumbers);
if(sumNumberContainer.length > 1){
for (var i = 0; i < sumNumberContainer.length - 1; i++) {
for (var j = i + 1; j < sumNumberContainer.length; j++) {
if(sumNumberContainer[i] == sumNumberContainer[j]){
return false;
}
}
}
}
return CheckIfNumberIsHappy(sumOfTheNumbers.toString());
}
}
Thanks for the great support :)