Pretty simple question - can someone provide a formula that takes 3 numbers (x,y,z) and converts them into a single integer between 0 and 32767.
1,1,2 and 2,1,1 shouldn't be the same resulting value (simply adding the numbers up isn't what I want) but compressing an infinite number of x,y,z into a small range of numbers obviously will get the same values back quite often.
The formula also needs to work on large numbers like 5000,5000,1000
If you need to go between 0 and 131068 that would be fine, but it shouldn't be much more than that.
One solution I can think of is to take each x,y,z and assign them each to a range of 5 bits in the 2^15 possible values in [0, 32767]. One way of doing this is taking each x,y,z modulo 2^5 (to compress them into the requisite 5 bits) and then set the bits of the result accordingly. The end result should look something like
def compress(x,y,z):
x %= 32
y %= 32
z %= 32
return x + (y<<5) + (z<<10)
print (compress(5000,5000,1000))
>>> 8456
Obviously this approach has colliding outputs very often (whenever x, y or z are the same modulo 32), but as you said this is pretty unavoidable.
I have 2 3D vectors. (objects with X, Y and Z float values)
In my diagram below, I would like to determine the length of the green line.
This is the distance along Vector 1 that Vector 2 is. Or, the distance from the origin to the end of a line on Vector 1 which is at 90' to Vector 1 and passes thorough the point at the end of Vector 2.
I am doing this in Unity3D so I have access to quite a few helper methods that enable me to get the length of a Vector3 and so on very easily.
The length is obviously
norm(v2)*cos(angle(v1,v2))
and since
cos(angle(v1,v2))=abs(dot(v1,v2))/norm(v1)/norm(v2)
the final formula is
abs(dot(v1,v2))/norm(v1)
One could also say that
e1 = v1/norm(v1)
is the unit vector in the direction of v1, and that the green vector is
dot(e1,v2)*e1
resulting in the same length formula.
This is projection of Vector2 onto Vector1 direction. The simplest way (I think) to find it - using scalar product
D = |V2| * DotProduct(V2, V1) / (|V2| * |V1|) = DotProduct(V2, V1) / |V1|
where |V1| is the length of V1 vector
Im not sure but I think this is what you wanted
Vector3 distance = Vector3.Lerp(Vector3.zero, vector_1, vector_2.sqrMagnitude / vector_1.sqrMagnitude);
http://docs.unity3d.com/ScriptReference/Vector3-sqrMagnitude.html
http://docs.unity3d.com/ScriptReference/Vector3.Lerp.html
Say we have a set of 3D (integer) coordinates from (0,0,0) to (100,100,100)
We want to visit each possible coordinate (100^3 possible coordinates to visit) without visiting each coordinate more than once.
The sum of the differences between each coordinate in adjacent steps cannot be more than 2 (I don't know if this is possible. If not, then minimized)
for example, the step from (0,2,1) to (2,0,0) has a total difference of 5 because |x1-x2|+|y1-y2|+|z1-z2| = 5
How do we generate such a sequence of coordinates?
for example, to start:
(0,0,0)
(0,0,1)
(0,1,0)
(1,0,0)
(1,0,1)
(0,0,2)
(0,1,1)
(0,2,0)
(1,1,0)
(2,0,0)
(3,0,0)
(2,0,1)
(1,0,2)
(0,0,3)
etc...
Anyone know an algorithm that will generate such a sequence to an arbitrary coordinate (x,y,z) where x=y=z or can prove that it is impossible for such and algorithm to exist? Thanks
Extra credit: Show how to generate such a sequence with x!=y!=z :D
One of the tricks (there are other approaches) is to do it one line [segment] at a time, one plane [square] at a time. Addressing the last part of the question, this approach works, even if the size of the volume visited is not the same in each dimension (ex: a 100 x 6 x 33 block).
In other words:
Start at (0,0,0),
move only on the Z axis till the end of the segment, i.e.
(0,0,1), (0,0,2), (0,0,3), ... (0,0,100),
Then move to the next line, i.e.
(0,1,100)
and come backward on the line, i.e.
(0,1,99), (0,1,98), (0,1,97), ... (0,1,0),
Next to the next line, going "forward"
And repeat till the whole "panel is painted", i.e ending at
... (0,100,99), (0,100,100),
Then move, finally, by 1, on the X axis, i.e.
(1,100,100)
and repeat on the other panel,but on this panel going "upward"
etc.
Essentially, each move is done on a single dimension, by exactly one. It is a bit as if you were "walking" from room to room in a 101 x 101 x 101 building where each room can lead to any room directly next to it on a given axis (i.e. not going joining diagonally).
Implementing this kind of of logic in a programming language is trivial! The only mildly challenging part is to deal with the "back-and-forth", i.e. the fact that sometimes, some of the changes in a given dimension are positive, and sometimes negative).
Edit: (Sid's question about doing the same diagonally):
Yes! that would be quite possible, since the problem states that we can have a [Manhattan] distance of two, which is what is required to go diagonally.
The path would be similar to the one listed above, i.e. doing lines, back-and-forth (only here lines of variable length), then moving to the next "panel", in the third dimension, and repeating, only going "upward" etc.
(0,0,0) (0,0,1)
(0,1,0) first diagonal, only 1 in lengh.
(0,2,0) "turn around"
(0,1,1) (0,0,2) second diagonal: 2 in length
(0,0,3) "turn around"
(0,1,2) (0,2,1) (0,3,0) third diagonal: 3 in length
(0,4,0) turn around
etc.
It is indeed possible to mix-and-match these approaches, both at the level of complete "panel", for example doing one diagonally and the next one horizontally, as well as within a given panel, for example starting diagonally, but when on the top line, proceeding with the horizontal pattern, simply stopping a bit earlier when looping on the "left" side, since part of that side has been handled with the diagonals.
Effectively this allows a rather big (but obviously finite) number of ways to "paint" the whole space. The key thing is to avoid leaving (too many) non painted adjacent area behind, for getting back to them may either bring us to a dead-end or may require a "jump" of more than 2.
Maybe you can generalize Gray Codes, which seem to solve a special case of the problem.
Seems trivial at first but once started, it is tricky! Especially the steps can be 1 or 2.
This is not an answer but more of a demostration of the first 10+ steps for a particular sequence which hopefully can help others to visualise. Sid, please let me know if the following is wrong:
s = No. of steps from the prev corrdinates
c1 = Condition 1 (x = y = z)
c2 = Condition 2 (x!= y!= z)
(x,y,z) s c1 c2
---------------
(0,0,0) * (start)
(0,0,1) 1
(0,1,0) 2
(1,0,0) 2
(1,0,1) 1
(1,1,0) 2
(1,1,1) 1 *
(2,1,1) 1
(2,0,1) 1 *
(2,0,0) 1
(2,1,0) 1 *
(2,2,0) 1
(2,2,1) 1
(2,2,2) 1 *
(2,3,2) 1
(2,3,3) 1
(3,3,3) 1 *
(3,3,1) 2
(3,2,1) 1 *
(3,2,0) 1 *
.
.
.
Ok here's what I'm trying to accomplish. Say I have 100 items. I want to create a "grid"(each Item consisting of an x, y point). I want the grid to be as close to a square as possible.
Is there any kind of math to determine the grid width, and grid height i'd need by just a single number?(By grid width and height I mean the number of x items, and the number of Y items)
Now that I think about it would it be efficient to take the square root of the number, say varI=sqrt(45), remove the decimal place from varI...X=varI...then Y would be varI+1?
The square root is precisely what you need.
N
x=floor(sqrt(N))
y=raise(N/x)
This is the minimum rectangle that has more than N places and is closest to a square.
Now... if you want to find a rectangle that has exactly N places and is closest to a square...that's a different problem.
You need to find a factor of N, x, that's closest
You have to run through the factors of N and find the closest to sqrt(N). Then the rectangle is x by N/x, both integers.
There are several issues to consider here. If you want your grid to be as square as possible, for many Ns it will have empty cells in it. A simple example is N=10. You can create a 3x4 grid for it, but it will have two empty cells. A 2x5 grid, on the other hand, will have no empty cells. Some Ns (prime numbers) will always have empty cells in the grid.
But if you just want the square and don't care about empty fields then generally yes, you should take the square root. Say your number is N. Then, take R = int(sqrt(N)). Next, do an integer division N/R, take the quotient and add 1 to it. This is C. The grid is RxC. Note that when N is a square (like 100), this is a special case so don't add 1 to the quotient.
Example:
N = 40
R = int(sqrt(N)) = 6
C = int(40 / 6) + 1 = 7
grid is 6x7
I was looking to solve this problem too for a grid in html/css that had fixed dimensions and where N items would fit. I ended up creating my own script for that in javascript.
If you're interested in the method and maths I used, you can read http://machinesaredigging.com/2013/05/21/jgridder-how-to-fit-elements-in-a-sized-grid/, it's all documented there. I used recursion and it works really well, you can use the same method for your own language. Hope this helps.
I explored Eli's answer and found something I'd like to point out. For the sake of generality, one must add 1 to C only if R x C (C = int(N/R)) is not exactly N. So, the exception includes both numbers with square root and numbers which are exactly the product of two integers.
For instance:
N = 12
R = 3
C = 4 (int(N/R))
Hope it helps.