Determine position of number in a grid of numbers centered around 0 and increasing in spiral - math

I've got the following grid of numbers centered around 0 and increasing in spiral. I need an algorithm which would receive number in spiral and return x; y - numbers of moves how to get to that number from 0. For example for number 9 it would return -2; -1. For 4 it would be 1; 1.
25|26|... etc.
24| 9|10|11|12
23| 8| 1| 2|13
22| 7| 0| 3|14
21| 6| 5| 4|15
20|19|18|17|16
This spiral can be slightly changed if it would help the algorithm to be better.
Use whatever language you like. I would really appreciate mathematical explanation.
Thank you.

First we need to determine which cycle (distance from center) and sector (north, east, south or west) we are in. Then we can determine the exact position of the number.
The first numbers in each cycle is as follows: 1, 9, 25
This is a quadratic sequence: first(n) = (2n-1)^2 = 4n^2 - 4n + 1
The inverse of this is the cycle-number: cycle(i) = floor((sqrt(i) + 1) / 2)
The length of a cycle is: length(n) = first(n+1) - first(n) = 8n
The sector will then be:
sector(i) = floor(4 * (i - first(cycle(i))) / length(cycle(i)))
Finally, to get the position, we need to extrapolate from the position of the first number in the cycle and sector.
To put it all together:
def first(cycle):
x = 2 * cycle - 1
return x * x
def cycle(index):
return (isqrt(index) + 1)//2
def length(cycle):
return 8 * cycle
def sector(index):
c = cycle(index)
offset = index - first(c)
n = length(c)
return 4 * offset / n
def position(index):
c = cycle(index)
s = sector(index)
offset = index - first(c) - s * length(c) // 4
if s == 0: #north
return -c, -c + offset + 1
if s == 1: #east
return -c + offset + 1, c
if s == 2: #south
return c, c - offset - 1
# else, west
return c - offset - 1, -c
def isqrt(x):
"""Calculates the integer square root of a number"""
if x < 0:
raise ValueError('square root not defined for negative numbers')
n = int(x)
if n == 0:
return 0
a, b = divmod(n.bit_length(), 2)
x = 2**(a+b)
while True:
y = (x + n//x)//2
if y >= x:
return x
x = y
Example:
>>> position(9)
(-2, -1)
>>> position(4)
(1, 1)
>>> position(123456)
(-176, 80)

Do you mean something like this? I did not implement any algorithm and the code can be written better but it works - that's always a start :) Just change the threshold value for whatever you wish and you'll get the result.
static int threshold=14, x=0, y=0;
public static void main(String[] args) {
int yChange=1, xChange=1, count=0;
while( !end(count) ){
for (int i = 0; i < yChange; i++) {
if( end(count) )return;
count++;
y--;
}
yChange++;
for (int i = 0; i < xChange; i++) {
if( end(count) )return;
count++;
x++;
}
xChange++;
for (int i = 0; i < yChange; i++) {
if( end(count) )return;
count++;
y++;
}
yChange++;
for (int i = 0; i < xChange; i++) {
if( end(count) )return;
count++;
x--;
}
xChange++;
}
}
public static boolean end(int count){
if(count<threshold){
return false;
}else{
System.out.println("count: "+count+", x: "+x+", y: "+y);
return true;
}
}

Related

FINDING total number of paths using backtracking

I'm trying to count total paths in a 20x20 grid(ProjectEuler #15) using backtracking.I've played around with it but the answer is always None. Any help would be appreciated(I know it can be solved using recursion or memoization but i want to solve it using backtracking)
def isvalid(maze,n,x,y):
if x<0 or y<0 or x>n or y>n :
return False
else: return True
def countPaths(maze,x,y,n,used,count):
if x==n-1 or y==n-1:
count+=1
return
if isvalid(maze,n,x,y):
used[x][y]=True
if (x+1<n and used[x+1][y]==False):
countPaths(maze,x+1,y,n,used,count)
if (x-1>0 and used[x-1][y]==False):
countPaths(maze,x-1,y,n,used,count)
if (y+1<n and used[x][y+1]==False):
countPaths(maze,x,y+1,n,used,count)
if (y-1>0 and used[x][y-1]==False):
countPaths(maze,x,y-1,n,used,count)
used[x][y]=False
return
Since in the base case, you are only returning 1 whenever end of row or column occurs it would yield wrong answer.
You should increment a counter signifying the number of times you are able to reach the final [n-1][n-1] i.e rightmost bottom cell.
bool isValid(int x, int y)
{
if (x < 0 || x >= n || y < 0 || y >= n)
return false;
return true;
}
void countPaths(int x, int y)
{
// cout << x << y << endl;
if (x == n - 1 && y == n - 1)
{
paths++;
return;
}
if (isValid(x, y))
{
visited[x][y] = true;
countPaths(x, y + 1);
countPaths(x + 1, y);
}
return;
}
Keeping paths & visited as global variables , I implemented the above approach.
For n=2 (1+1): 2
For n=3 (2+1): 6
For n=4 (3+1): 20
For n=5 (4+1): 70
however, this approach would not be viable for n=20.
I would suggest trying Dynamic Programming as it would simplify the process!

Converting grid coordinates

So I have a grid which is in one form and im trying to get the X and Y.
Is there a formula where I could turn for example 12 into 2,2 or 14 to 2,3
Also is there a name for this type of grid?
static int getX(int z)
{
int count = 0;
int res = 0;
int curr = 0;
for(int temp = z; temp > 0; temp >>= 1)
{
if(count % 2 ==0)
{
res += ((temp & 1) << curr);
curr++;
}
count++;
}
return res;
}
static int getY(int z)
{
int count = 0;
int res = 0;
int curr = 0;
for(int temp = z; temp > 0; temp >>= 1)
{
if(count % 2 ==1)
{
res += ((temp & 1) << curr);
curr++;
}
count++;
}
return res;
}
As Sneftel observed, this looks like a Z-order curve. As such, you can convert coordinates by interleaving binary representations. So your examples are
0 1 0 x=2 0 1 0 x=2
0 1 0 y=2 0 1 1 y=3
001100 p=12 001110 p=14
So to get x and y coordinates from the cell number p, you assign the bits of p alternatingly to x and y. This kind of bit arithmetic is pretty hard to express using elementary arithmetic operations, and there is no generally recognized formula symbol for this that I'm aware of, but the idea is quite simple.

How to get a logarithmic distribution from an interval

I am currently trying to cut an interval into not equal-width slices. In fact I want the width of each slice to follow a logarithmic rule. For instance the first interval is supposed to be bigger than the second one, etc.
I have a hard time remembering my mathematics lectures. So assuming I know a and b which are respectively the lower and upper boundaries of my interval I, and n is the number of slices:
how can I find the lower and upper boundaries of each slice (following a logarithmic scale)?
In other word, here's what I have done to get equal-width interval:
for (i = 1; i< p; i++) {
start = lower + i -1 + ((i-1) * size_piece);
if (i == p-1 ) {
end = upper;
} else {
end = start + size_piece;
}
//function(start, end)
}
Where: p-1= number of slices, and size_piece = |b-a|.
What I want to get now is start and end values, but following a logarithmic scale instead of an arithmetic scale (which are going to be called in some function in the for loop).
Thanks in advance for your help.
If I have understood your question, this C++ program will show you a practical example of the algorithm that can be used:
#include <iostream>
#include <cmath>
void my_function( double a, double b ) {
// print out the lower and upper bounds of the slice
std::cout << a << " -- " << b << '\n';
}
int main() {
double start = 0.0, end = 1.0;
int n_slices = 7;
// I want to create 7 slices in a segment of length = end - start
// whose extremes are logarithmically distributed:
// | 1 | 2 | 3 | 4 | 5 |6 |7|
// +-----------------+----------+------+----+---+--+-+
// start end
double scale = (end - start) / log(1.0 + n_slices);
double lower_bound = start;
for ( int i = 0; i < n_slices; ++i ) {
// transform to the interval (1,n_slices+1):
// 1 2 3 4 5 6 7 8
// +-----------------+----------+------+----+---+--+-+
// start end
double upper_bound = start + log(2.0 + i) * scale;
// use the extremes in your function
my_function(lower_bound,upper_bound);
// update
lower_bound = upper_bound;
}
return 0;
}
The output (the extremes of the slices) is:
0 -- 0.333333
0.333333 -- 0.528321
0.528321 -- 0.666667
0.666667 -- 0.773976
0.773976 -- 0.861654
0.861654 -- 0.935785
0.935785 -- 1

Challenge with vector: how to split a vector based on max/min conditions

I've recently come across the following problem:
Let say I have an vector of random length (L) of 0 and 1 randomly distributed (for example [0,1,1,1,0,0,1,0]), I need to split the vector in two sub-vector at index K so following conditions are valid:
the left sub-vector must contains the maximum number of elements from
K in reverse order such as the number of zeros must be greater or
equal to the number of 1s
the right sub vector must contains the maximum number of element starting from K+1 such as the number of 1s must be greater or equal to the number of zeros
For example, [1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0] the split is at index 9, left vector is [1,0], right vector [0,1]
I wrote the following solution but the complexity is O(L^2). I think there could be a solution with complexity of worst case O(L) but I cannot find anything that can help me. Any idea? Thanks
var max = 0;
var kMax = -1;
var firstZeroFound = false;
for (var i = 0; i < testVector.Length - 1; i++)
{
if (!firstZeroFound)
{
if (testVector[i]) continue;
firstZeroFound = true;
}
var maxZero = FindMax(testVector, i, -1, -1, false);
if (maxZero == 0) continue;
var maxOne = FindMax(testVector, i + 1, testVector.Length, 1, true);
if (maxOne == 0) continue;
if ((maxZero + maxOne) <= max)
continue;
max = maxOne + maxZero;
kMax = i;
if (max == testVector.Length)
break;
}
Console.Write("The result is {0}", kMax);
int FindMax(bool[] v, int start, int end, int increment, bool maximize)
{
var max = 0;
var sum = 0;
var count = 0;
var i = start;
while (i != end)
{
count++;
if (v[i])
sum++;
if (maximize)
{
if (sum * 2 >= count)
max = count;
}
else if (sum * 2 <= count)
{
max = count;
}
i += increment;
}
return max;
}
I think you should look at rle.
y <- c(1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0)
z <- rle(y)
d <- cbind(z$values, z$lengths)
[,1] [,2]
[1,] 1 9
[2,] 0 1
[3,] 1 1
[4,] 0 8
Basically, rle calculates the lengths of 0's and 1's at each level.
From here things may go easier for you.

Optimization of Fibonacci sequence generating algorithm

As we all know, the simplest algorithm to generate Fibonacci sequence is as follows:
if(n<=0) return 0;
else if(n==1) return 1;
f(n) = f(n-1) + f(n-2);
But this algorithm has some repetitive calculation. For example, if you calculate f(5), it will calculate f(4) and f(3). When you calculate f(4), it will again calculate both f(3) and f(2). Could someone give me a more time-efficient recursive algorithm?
I have read about some of the methods for calculating Fibonacci with efficient time complexity following are some of them -
Method 1 - Dynamic Programming
Now here the substructure is commonly known hence I'll straightly Jump to the solution -
static int fib(int n)
{
int f[] = new int[n+2]; // 1 extra to handle case, n = 0
int i;
f[0] = 0;
f[1] = 1;
for (i = 2; i <= n; i++)
{
f[i] = f[i-1] + f[i-2];
}
return f[n];
}
A space-optimized version of above can be done as follows -
static int fib(int n)
{
int a = 0, b = 1, c;
if (n == 0)
return a;
for (int i = 2; i <= n; i++)
{
c = a + b;
a = b;
b = c;
}
return b;
}
Method 2- ( Using power of the matrix {{1,1},{1,0}} )
This an O(n) which relies on the fact that if we n times multiply the matrix M = {{1,1},{1,0}} to itself (in other words calculate power(M, n )), then we get the (n+1)th Fibonacci number as the element at row and column (0, 0) in the resultant matrix. This solution would have O(n) time.
The matrix representation gives the following closed expression for the Fibonacci numbers:
fibonaccimatrix
static int fib(int n)
{
int F[][] = new int[][]{{1,1},{1,0}};
if (n == 0)
return 0;
power(F, n-1);
return F[0][0];
}
/*multiplies 2 matrices F and M of size 2*2, and
puts the multiplication result back to F[][] */
static void multiply(int F[][], int M[][])
{
int x = F[0][0]*M[0][0] + F[0][1]*M[1][0];
int y = F[0][0]*M[0][1] + F[0][1]*M[1][1];
int z = F[1][0]*M[0][0] + F[1][1]*M[1][0];
int w = F[1][0]*M[0][1] + F[1][1]*M[1][1];
F[0][0] = x;
F[0][1] = y;
F[1][0] = z;
F[1][1] = w;
}
/*function that calculates F[][] raise to the power n and puts the
result in F[][]*/
static void power(int F[][], int n)
{
int i;
int M[][] = new int[][]{{1,1},{1,0}};
// n - 1 times multiply the matrix to {{1,0},{0,1}}
for (i = 2; i <= n; i++)
multiply(F, M);
}
This can be optimized to work in O(Logn) time complexity. We can do recursive multiplication to get power(M, n) in the previous method.
static int fib(int n)
{
int F[][] = new int[][]{{1,1},{1,0}};
if (n == 0)
return 0;
power(F, n-1);
return F[0][0];
}
static void multiply(int F[][], int M[][])
{
int x = F[0][0]*M[0][0] + F[0][1]*M[1][0];
int y = F[0][0]*M[0][1] + F[0][1]*M[1][1];
int z = F[1][0]*M[0][0] + F[1][1]*M[1][0];
int w = F[1][0]*M[0][1] + F[1][1]*M[1][1];
F[0][0] = x;
F[0][1] = y;
F[1][0] = z;
F[1][1] = w;
}
static void power(int F[][], int n)
{
if( n == 0 || n == 1)
return;
int M[][] = new int[][]{{1,1},{1,0}};
power(F, n/2);
multiply(F, F);
if (n%2 != 0)
multiply(F, M);
}
Method 3 (O(log n) Time)
Below is one more interesting recurrence formula that can be used to find nth Fibonacci Number in O(log n) time.
If n is even then k = n/2:
F(n) = [2*F(k-1) + F(k)]*F(k)
If n is odd then k = (n + 1)/2
F(n) = F(k)*F(k) + F(k-1)*F(k-1)
How does this formula work?
The formula can be derived from the above matrix equation.
fibonaccimatrix
Taking determinant on both sides, we get
(-1)n = Fn+1Fn-1 – Fn2
Moreover, since AnAm = An+m for any square matrix A, the following identities can be derived (they are obtained from two different coefficients of the matrix product)
FmFn + Fm-1Fn-1 = Fm+n-1
By putting n = n+1,
FmFn+1 + Fm-1Fn = Fm+n
Putting m = n
F2n-1 = Fn2 + Fn-12
F2n = (Fn-1 + Fn+1)Fn = (2Fn-1 + Fn)Fn (Source: Wiki)
To get the formula to be proved, we simply need to do the following
If n is even, we can put k = n/2
If n is odd, we can put k = (n+1)/2
public static int fib(int n)
{
if (n == 0)
return 0;
if (n == 1 || n == 2)
return (f[n] = 1);
// If fib(n) is already computed
if (f[n] != 0)
return f[n];
int k = (n & 1) == 1? (n + 1) / 2
: n / 2;
// Applyting above formula [See value
// n&1 is 1 if n is odd, else 0.
f[n] = (n & 1) == 1? (fib(k) * fib(k) +
fib(k - 1) * fib(k - 1))
: (2 * fib(k - 1) + fib(k))
* fib(k);
return f[n];
}
Method 4 - Using a formula
In this method, we directly implement the formula for the nth term in the Fibonacci series. Time O(1) Space O(1)
Fn = {[(√5 + 1)/2] ^ n} / √5
static int fib(int n) {
double phi = (1 + Math.sqrt(5)) / 2;
return (int) Math.round(Math.pow(phi, n)
/ Math.sqrt(5));
}
Reference: http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibFormula.html
Look here for implementation in Erlang which uses formula
. It shows nice linear resulting behavior because in O(M(n) log n) part M(n) is exponential for big numbers. It calculates fib of one million in 2s where result has 208988 digits. The trick is that you can compute exponentiation in O(log n) multiplications using (tail) recursive formula (tail means with O(1) space when used proper compiler or rewrite to cycle):
% compute X^N
power(X, N) when is_integer(N), N >= 0 ->
power(N, X, 1).
power(0, _, Acc) ->
Acc;
power(N, X, Acc) ->
if N rem 2 =:= 1 ->
power(N - 1, X, Acc * X);
true ->
power(N div 2, X * X, Acc)
end.
where X and Acc you substitute with matrices. X will be initiated with and Acc with identity I equals to .
One simple way is to calculate it iteratively instead of recursively. This will calculate F(n) in linear time.
def fib(n):
a,b = 0,1
for i in range(n):
a,b = a+b,a
return a
Hint: One way you achieve faster results is by using Binet's formula:
Here is a way of doing it in Python:
from decimal import *
def fib(n):
return int((Decimal(1.6180339)**Decimal(n)-Decimal(-0.6180339)**Decimal(n))/Decimal(2.236067977))
you can save your results and use them :
public static long[] fibs;
public long fib(int n) {
fibs = new long[n];
return internalFib(n);
}
public long internalFib(int n) {
if (n<=2) return 1;
fibs[n-1] = fibs[n-1]==0 ? internalFib(n-1) : fibs[n-1];
fibs[n-2] = fibs[n-2]==0 ? internalFib(n-2) : fibs[n-2];
return fibs[n-1]+fibs[n-2];
}
F(n) = (φ^n)/√5 and round to nearest integer, where φ is the golden ratio....
φ^n can be calculated in O(lg(n)) time hence F(n) can be calculated in O(lg(n)) time.
// D Programming Language
void vFibonacci ( const ulong X, const ulong Y, const int Limit ) {
// Equivalent : if ( Limit != 10 ). Former ( Limit ^ 0xA ) is More Efficient However.
if ( Limit ^ 0xA ) {
write ( Y, " " ) ;
vFibonacci ( Y, Y + X, Limit + 1 ) ;
} ;
} ;
// Call As
// By Default the Limit is 10 Numbers
vFibonacci ( 0, 1, 0 ) ;
EDIT: I actually think Hynek Vychodil's answer is superior to mine, but I'm leaving this here just in case someone is looking for an alternate method.
I think the other methods are all valid, but not optimal. Using Binet's formula should give you the right answer in principle, but rounding to the closest integer will give some problems for large values of n. The other solutions will unnecessarily recalculate the values upto n every time you call the function, and so the function is not optimized for repeated calling.
In my opinion the best thing to do is to define a global array and then to add new values to the array IF needed. In Python:
import numpy
fibo=numpy.array([1,1])
last_index=fibo.size
def fib(n):
global fibo,last_index
if (n>0):
if(n>last_index):
for i in range(last_index+1,n+1):
fibo=numpy.concatenate((fibo,numpy.array([fibo[i-2]+fibo[i-3]])))
last_index=fibo.size
return fibo[n-1]
else:
print "fib called for index less than 1"
quit()
Naturally, if you need to call fib for n>80 (approximately) then you will need to implement arbitrary precision integers, which is easy to do in python.
This will execute faster, O(n)
def fibo(n):
a, b = 0, 1
for i in range(n):
if i == 0:
print(i)
elif i == 1:
print(i)
else:
temp = a
a = b
b += temp
print(b)
n = int(input())
fibo(n)

Resources