I have a 2D grid of integers. The user can pick any location and increase or decrease its number by one. The algorithm should adjust all eight adjacent locations so there is no more than a difference of one between them.
I've go things working mostly but there must be an edge case I'm missing as after making a few adjustments one of the locations can go wonky (much more of a difference than one).
Here is a screenshot of the grid once it goes wonky.
The javascript to so this is
var moveDown = function (x, y) {
var updated = false;
if (x-1 >= 0 && Math.abs(grid[x][y] - grid[x-1][y]) > 1) {
grid[x-1][y] -= 1;
updated = true;
}
if (x+1 < size && Math.abs(grid[x][y] - grid[x+1][y]) > 1) {
grid[x+1][y] -= 1;
updated = true;
}
if (y-1 >= 0 && Math.abs(grid[x][y] - grid[x][y-1]) > 1) {
grid[x][y-1] -= 1;
updated = true;
}
if (y+1 < size && Math.abs(grid[x][y] - grid[x][y+1]) > 1) {
grid[x][y+1] -= 1;
updated = true;
}
if (x-1 >= 0 && y-1 >= 0 && Math.abs(grid[x][y] - grid[x-1][y-1]) > 1) {
grid[x-1][y-1] -= 1;
updated = true;
}
if (x-1 >= 0 && y+1 < size && Math.abs(grid[x][y] - grid[x-1][y+1]) > 1) {
grid[x-1][y+1] -= 1;
updated = true;
}
if (x+1 < size && y-1 >= 0 && Math.abs(grid[x][y] - grid[x+1][y-1]) > 1) {
grid[x+1][y-1] -= 1;
updated = true;
}
if (x+1 < size && y+1 < size && Math.abs(grid[x][y] - grid[x+1][y+1]) > 1) {
grid[x+1][y+1] -= 1;
updated = true;
}
if (updated) {
if (x-1 >= 0) { moveDown(x-1, y); }
if (x+1 < size) { moveDown(x+1, y); }
if (y-1 >= 0) { moveDown(x, y-1); }
if (y+1 < size) { moveDown(x, y+1); }
if (x-1 >= 0 && y-1 >= 0) { moveDown(x-1, y-1); }
if (x-1 >= 0 && y+1 < size) { moveDown(x-1, y+1); }
if (x+1 < size && y-1 >= 0) { moveDown(x+1, y-1); }
if (x+1 < size && y+1 < size) { moveDown(x+1, y+1); }
}
}
I've got a fiddle here that I've been using to play with things.
How can I fix things to make it work properly?
As pointed out in comments, your code is recursive, and in some situations it hits an infinite recursion.
When that infinite recursion is triggered, the outcome depends on the Javascript engine being used. In some versions, an error message "Uncaught RangeError: Maximum call stack size exceeded" will appear in the error console. (This is the case for Chrome.) Other Javascript engines may handle it differently, and maybe in not-so-nice ways.
The unusual numerical values are displayed only if the Javascript engine interrupts the execution and still refreshes the page rendering (without executing the code further).
You can implement your original idea using for-loops, without using recursion.
You can get some ideas from Morphological Image Processing.
Related
please if there is any specific algorithm for implementing the divide operator as a function, guide me about their name. I want to implement a function that takes two floating number and return the result of the divide, but in implementation, I won't use "/".
I have done this in a much simpler version when we want just the q in integer,
function divide(num0, num1) {
if ("bigint" != typeof num0 || "bigint" != typeof num1) {
throw new TypeError("The arguments should be bigint.");
}
if (num1 > num0) {
return 0;
}
for (var i = 0n; num0 >= num1; i++) {
num0 -= num1;
}
return i;
}
"I use bigint numeric type just two restrict to integer"
but I think this approach couldn't extend two return floating results. my guess is I approach binary level operation or so; thanks if learning me about any flowchart, pseudo-code, or code-snippet "in any language" to deal with this problem
I wrote this one for this question in js:
function justIntegerDivide(num0, num1) {
for (var q = 0; num0 >= num1; q++) {
num0 -= num1;
}
return [q, num0];
}
const divide = (n0, n1, afterPoint = 10) => {
if ((0 == n1 || 0n == n1) && 0 < n0) return Infinity;
if ((0 == n1 || 0n == n1) && 0 > n0) return -Infinity;
if ((0 == n1 || 0n == n1) && 0 == n0) return NaN;
if ("number" == typeof n0 && "number" == typeof n1) {
let sign = Math.sign(n0) * Math.sign(n1);
let num0 = Math.abs(n0),
num1 = Math.abs(n1);
let counter = 0;
let [q, r] = justIntegerDivide(num0, num1);
result = `${q}.`;
for (counter = 1; counter < afterPoint; counter++) {
var newReminder;
let qAfter;
previousReminder = 1 == counter ? r : newReminder;
[qAfter, newReminder] = justIntegerDivide(previousReminder * 10, num1);
result += qAfter;
if (0 == newReminder) {
return +result * sign;
}
}
return +result * sign;
} else if ("bigint" == typeof n0 && "bigint" == typeof n1) {
let sign = (n0 > 0 && n1 > 0) || (n0 < 0 && n1 < 0) ? 1n : -1n;
let num0 = n0 > 0 ? n0 : -n0;
let num1 = n1 > 0 ? n1 : -n1;
if (num0 < num1) {
return 0n;
}
for (var i = 0n; num0 >= num1; i++) {
num0 -= num1;
}
return i * sign;
} else {
throw new TypeError("Both arguments should be number or bigint");
}
};
I have worked on this problem for days but still, couldn't figure out a way to solve it. My solution can't solve some edge cases.
Problem:
Given an array and sorted in ascending order, rotate the array by k elements, find the index of the minimum number of the array(first element of the original non-rotated array).For example:
1. Give {3,4,1,3,3}, return 2.
2. Give {3,3,3,3,3}, return 0.
3. Give {1,1,4,1,1,1}, return 3.
Without duplicates, this problem can be solved in O(logn) time using binary search, with duplicates a modified binary search can be used, worst case time complexity is O(n).
My code:
public int FindPivot(int[] array)
{
var i = 0;
var j = array.Length - 1;
while (i < j)
{
var mid = i + (j - i) / 2 + 1;
if (array[mid] < array[array.Length - 1])
{
j = mid - 1;
}
else if (array[mid] > array[array.Length - 1])
{
i = mid;
}
else
{
if (array[mid] == array[j])
{
j--;
}
if (array[mid] == array[i])
{
i++;
}
}
}
return i+1;
}
It doesn't work if the input is {3,3,1,3,3,3,3,3}, it returns 3 while the correct answer is 2. Because at the last step is i points to index 2 and j moves from index 3 to index 2, it gets the correct element but i+1 makes the result wrong.What am I missing here?
I have modified your code as below and it seems works for all cases.
I cannot think of any good way to handle all the corner cases, because your original code kind of mix up the concept of the algorithm without duplicate elements (divide into two sub arrays) and two-pointers algorithm when there is duplicate elements.
I would say the problem is that the else case which is moving the two pointers did not cover all cases, like there are chances that you will go into else block with array[i] < array[mid]
Therefore I just modified it using newbie's method: Add two variables to keep track the minimum element and minimum index we found. Update it whenever the pointers move to cover all the cases possible. Return the index at the end. You cannot do something like return i+1 as it won't handle case for k = 0 which is no rotation at all ( {1,2,3,4})
The modified code is written in C# which I guess from your sample code.
PS: Though in average, this is faster than O(N) if the data is partially sorted without duplicate elements, it's worst case is still O(N) as you mentioned. So if I were you, I would just do a simple iteration and find the first minimum element...
Also from this reference, O(N) is the optimal you can reach if there are duplicate elements.
http://ideone.com/v3KVwu
using System;
public class Test
{
public static int FindPivot(int[] array)
{
var i = 0;
var j = array.Length - 1;
var ans = 1<<20;
var idx = 1<<20;
while (i < j)
{
var mid = i + (j - i) / 2 + 1;
// Console.WriteLine(String.Format("{0}, {1}, {2}", i, mid, j));
if (array[mid] < array[array.Length - 1])
{
if(array[mid] < ans || (array[mid] == ans && mid < idx)) { ans = array[mid]; idx = mid;}
j = mid - 1;
}
else if (array[mid] > array[array.Length - 1])
{
i = mid;
}
else
{
// Here did not consider case if array[i] < mid
if(array[j] < ans || (array[j] == ans && j < idx)) { ans = array[j]; idx = j;}
if(array[i] < ans || (array[i] == ans && i < idx)) { ans = array[i]; idx = i;}
if (array[mid] == array[j])
{
j--;
}
if (array[mid] == array[i])
{
i++;
}
}
}
if(array[j] < ans || (array[j] == ans && j < idx)) { ans = array[j]; idx = j;}
if(array[i] < ans || (array[i] == ans && i < idx)) { ans = array[i]; idx = i;}
Console.WriteLine("Minimum = " + ans);
return idx;
}
public static void Main()
{
int []a = {7,7,7,7,8,8,9,9,1,2,2,2,7,7};
int []b = {3,3,1,3,3,3,3,3};
int []c = {1,2,3,4};
int []d = {4,4,4,4};
int []e = {3,3,3,3,3,3,3,1,3};
int []f = {4,5,6,7,1,1,1,1};
Console.WriteLine(FindPivot(a));
Console.WriteLine(FindPivot(b));
Console.WriteLine(FindPivot(c));
Console.WriteLine(FindPivot(d));
Console.WriteLine(FindPivot(e));
Console.WriteLine(FindPivot(f));
}
}
Based on #shole's answer, I modified the code a little bit to cover cases like {1,1,1,1,3,1,1,1,1,1,1,1,1}.
public int FindPivot(int[] nums)
{
var i = 0;
var j = nums.Length - 1;
var ans = int.MaxValue;
var idx = int.MaxValue;
while (i < j)
{
var mid = i + (j - i) / 2 + 1;
if (nums[mid] < nums[nums.Length - 1])
{
if (nums[mid] < ans || (nums[mid] == ans && mid < idx)) { ans = nums[mid]; idx = mid; }
j = mid - 1;
}
else if (nums[mid] > nums[nums.Length - 1])
{
i = mid;
}
else
{
if (nums[j] < ans || (nums[j] == ans && j < idx)) { ans = nums[j]; idx = j; }
if (nums[mid] == nums[j])
{
j--;
}
if (nums[mid] == nums[i])
{
i++;
}
}
}
// Deal with cases like {1,1,1,1,1}
if (nums[i] == nums[nums.Length - 1] && nums[i] == nums[0] && i == j)
{
return 0;
}
if (nums[j] < ans || (nums[j] == ans && j < idx)) { ans = nums[j]; idx = j; }
return idx;
}
I'd been trying to program a Numbrix generator with two conditions:
Square grid 10 x 10
Number 1 is on the bottom row of the grid and 100 on the top row
Rules of Numbrix are that every number must have a side (in the grid) in common with the following number.
I'd been trying to make an algorithm that generates a random grid that satisfies what I said and I'd been unable of doing so. My main attempt was to simply keep trying a path randomly, going back when needed, until I ended up with a path that finished with 100 on top row, but that seemed to be too inefficient.
I hoped to find here a guideline on how to build such algorithm.
I'd been trying to do so in C++, but since the main issue here is the algorithm, language shouldn't be the issue.
Here's my algorithm right now:
int nrow = 10;
int ncol = 10;
typedef vector< vector<int> > matrix;
bool generate_path(int x, int y, matrix &grid, int value, int maxused)
{
if(x == 0) maxused++;
if(maxused == ncol && value != nrow*ncol) return(false);
grid[x][y] = value;
if(grid[x][y] == nrow * ncol)
{
if(x == 0) return(true);
grid[x][y] = 0;
return(false);
}
// 0: North, 1: East, 2: South, 3: West
bool directions[4];
directions[0] = y+1 < ncol && grid[x][y+1] == 0;
directions[1] = x+1 < nrow && grid[x+1][y] == 0;
directions[2] = y > 0 && grid[x][y-1] == 0;
directions[3] = x > 0 && grid[x-1][y] == 0;
while(directions[0] || directions[1] || directions[2] || directions[3])
{
int direction = rand() % 4;
while(!directions[direction]) direction = rand() % 4;
switch(direction)
{
case 0:
if(generate_path(x, y+1, grid, value+1, maxused)) return(true);
directions[direction] = false;
break;
case 1:
if(generate_path(x+1, y, grid, value+1, maxused)) return(true);
directions[direction] = false;
break;
case 2:
if(generate_path(x, y-1, grid, value+1, maxused)) return(true);
directions[direction] = false;
break;
case 3:
if(generate_path(x-1, y, grid, value+1, maxused)) return(true);
directions[direction] = false;
break;
}
}
grid[x][y] = 0;
return(false);
}
matrix generate_grid(const int &mult)
{
matrix grid(nrow, vector<int> (ncol, 0));
int x = nrow-1;
int y = rand() % ncol;
generate_path(x, y, grid, 1, 0);
for(int i = 0; i < nrow; i++) for(int j = 0; j < ncol; j++) grid[i][j] = grid[i][j] * mult;
return grid;
}
When I do Numbrix, I've noticed that the numbers are usually in random places, but there is always a bridge of numbers to get to the other number, and there are no blockages.
You could just write out a Numbrix yourself on paper instead of trying to figure it out on the computer. Or, you could look up Numbrix and write down theirs, but alter it a little to your own liking. Hope this helps!
I'm trying to get the nth root of a number using JavaScript, but I don't see a way to do it using the built in Math object. Am I overlooking something?
If not...
Is there a math library I can use that has this functionality?
If not...
What's the best algorithm to do this myself?
Can you use something like this?
Math.pow(n, 1/root);
eg.
Math.pow(25, 1/2) == 5
The nth root of x is the same as x to the power of 1/n. You can simply use Math.pow:
var original = 1000;
var fourthRoot = Math.pow(original, 1/4);
original == Math.pow(fourthRoot, 4); // (ignoring floating-point error)
Use Math.pow()
Note that it does not handle negative nicely - here is a discussion and some code that does
http://cwestblog.com/2011/05/06/cube-root-an-beyond/
function nthroot(x, n) {
try {
var negate = n % 2 == 1 && x < 0;
if(negate)
x = -x;
var possible = Math.pow(x, 1 / n);
n = Math.pow(possible, n);
if(Math.abs(x - n) < 1 && (x > 0 == n > 0))
return negate ? -possible : possible;
} catch(e){}
}
You could use
Math.nthroot = function(x,n) {
//if x is negative function returns NaN
return this.exp((1/n)*this.log(x));
}
//call using Math.nthroot();
For the special cases of square and cubic root, it's best to use the native functions Math.sqrt and Math.cbrt respectively.
As of ES7, the exponentiation operator ** can be used to calculate the nth root as the 1/nth power of a non-negative base:
let root1 = Math.PI ** (1 / 3); // cube root of π
let root2 = 81 ** 0.25; // 4th root of 81
This doesn't work with negative bases, though.
let root3 = (-32) ** 5; // NaN
The n-th root of x is a number r such that r to the power of 1/n is x.
In real numbers, there are some subcases:
There are two solutions (same value with opposite sign) when x is positive and r is even.
There is one positive solution when x is positive and r is odd.
There is one negative solution when x is negative and r is odd.
There is no solution when x is negative and r is even.
Since Math.pow doesn't like a negative base with a non-integer exponent, you can use
function nthRoot(x, n) {
if(x < 0 && n%2 != 1) return NaN; // Not well defined
return (x < 0 ? -1 : 1) * Math.pow(Math.abs(x), 1/n);
}
Examples:
nthRoot(+4, 2); // 2 (the positive is chosen, but -2 is a solution too)
nthRoot(+8, 3); // 2 (this is the only solution)
nthRoot(-8, 3); // -2 (this is the only solution)
nthRoot(-4, 2); // NaN (there is no solution)
Well, I know this is an old question. But, based on SwiftNinjaPro's answer, I simplified the function and fixed some NaN issues. Note: This function used ES6 feature, arrow function and template strings, and exponentation. So, it might not work in older browsers:
Math.numberRoot = (x, n) => {
return (((x > 1 || x < -1) && n == 0) ? Infinity : ((x > 0 || x < 0) && n == 0) ? 1 : (x < 0 && n % 2 == 0) ? `${((x < 0 ? -x : x) ** (1 / n))}${"i"}` : (n == 3 && x < 0) ? -Math.cbrt(-x) : (x < 0) ? -((x < 0 ? -x : x) ** (1 / n)) : (n == 3 && x > 0 ? Math.cbrt(x) : (x < 0 ? -x : x) ** (1 / n)));
};
Example:
Math.numberRoot(-64, 3); // Returns -4
Example (Imaginary number result):
Math.numberRoot(-729, 6); // Returns a string containing "3i".
Here's a function that tries to return the imaginary number. It also checks for a few common things first, ex: if getting square root of 0 or 1, or getting 0th root of number x
function root(x, n){
if(x == 1){
return 1;
}else if(x == 0 && n > 0){
return 0;
}else if(x == 0 && n < 0){
return Infinity;
}else if(n == 1){
return x;
}else if(n == 0 && x > 1){
return Infinity;
}else if(n == 0 && x == 1){
return 1;
}else if(n == 0 && x < 1 && x > -1){
return 0;
}else if(n == 0){
return NaN;
}
var result = false;
var num = x;
var neg = false;
if(num < 0){
//not using Math.abs because I need the function to remember if the number was positive or negative
num = num*-1;
neg = true;
}
if(n == 2){
//better to use square root if we can
result = Math.sqrt(num);
}else if(n == 3){
//better to use cube root if we can
result = Math.cbrt(num);
}else if(n > 3){
//the method Digital Plane suggested
result = Math.pow(num, 1/n);
}else if(n < 0){
//the method Digital Plane suggested
result = Math.pow(num, 1/n);
}
if(neg && n == 2){
//if square root, you can just add the imaginary number "i=√-1" to a string answer
//you should check if the functions return value contains i, before continuing any calculations
result += 'i';
}else if(neg && n % 2 !== 0 && n > 0){
//if the nth root is an odd number, you don't get an imaginary number
//neg*neg=pos, but neg*neg*neg=neg
//so you can simply make an odd nth root of a negative number, a negative number
result = result*-1;
}else if(neg){
//if the nth root is an even number that is not 2, things get more complex
//if someone wants to calculate this further, they can
//i'm just going to stop at *n√-1 (times the nth root of -1)
//you should also check if the functions return value contains * or √, before continuing any calculations
result += '*'+n+√+'-1';
}
return result;
}
I have written an algorithm but it is slow when you need many numbers after the point:
https://github.com/am-trouzine/Arithmetic-algorithms-in-different-numeral-systems
NRoot(orginal, nthRoot, base, numbersAfterPoint);
The function returns a string.
E.g.
var original = 1000;
var fourthRoot = NRoot(original, 4, 10, 32);
console.log(fourthRoot);
//5.62341325190349080394951039776481
This is embarrassing, but:
Let say I want to add 1 to x until it reaches 100. At that point I then want to subtract 1 from x until it reaches 1. Then I want to add 1 to x until it reaches 100, and so on.
Could someone provide some simple pseudocode to this question that is making me feel especially dumb.
Thanks :)
EDIT 1
Apologies! I made my example too simple. I actually will be incrementing using a random number at each iteration, so responses that require (x == 100) would not work as x will surely go above 100 and below 1.
Here is math way:
for(int i=0;i<10000000;i++)
print(abs(i%200-100))
Algo's way:
int i = 1;
while(1)
{
while(i<100)print(i++);
while(i>1)print(--i);
}
Random updated:
int i = 1;
while(1)
{
while(i<100)print(i=min(100,i+random()));
while(i>1)print(i=max(1,i-random()));
}
int ceiling = 100;
int floor = 1;
int x = 1;
int step = GetRandomNumber(); //assume this isn't 0
while(someArbitraryCuttoffOrAlwaysTrueIDK) {
while(x + step <= ceiling) {
x += step;
}
while(x - step >= floor) {
x -= step;
}
}
Or, being more concise (at the risk of being less clear):
while(someArbitraryCuttoffOrAlwaysTrueIDK) {
while((step > 0 && x + step <= ceiling) || (step < 0 && x + step >= floor))
{
x += step;
}
step = step * -1;
}
Alternatively:
while(someArbitraryCuttoffOrAlwaysTrueIDK) {
if((step > 0 && x + step > ceiling) || (step < 0 && x + step < floor))
{
step = step * -1;
}
x += step;
}
C#:
Random rnd = new Random();
int someVarToIncreaseDecrease = 0;
bool increasing = true;
while(true) {
int addSubtractInt = rnd.Next(someUpperBound);
if (increasing && (someVarToIncreaseDecrease + addSubtractInt >= 100))
increasing = false;
else if (!increasing && (someVarToIncreaseDecrease - addSubtractInt < 0))
increasing = true;
if (increasing) {
someVarToIncreaseDecrease += addSubtractInt;
}
else {
someVarToIncreaseDecrease -= addSubtractInt;
}
}