Traverse an n-dimensional array when dimensions are variable - algorithm

I need to traverse an n-dimensional array. The array is build and passed from another function and number of dimensions is not known in advance. This needs to be done in a primitive language similar to VBA. So, no python sort of goodness is present.
Does anyone know how this can be accomplished?
A sample array could be like a 5 x 6 x 1 x 8 array. So, it is a 4 dimensional array with dimension1=5, dimention2=6, dimension3=1 and dimension4=8.
I need to traverse each of the 5*6*1*8= 240 elements and record my results somehow so that I can relate my results with elements.
EDIT: TO make it more clear, at the end of the traversal, I want to be able to say that element at position (2,3,1,5) is x. So, I need to record the position of the element within the array and the element itself.
THe array in question is more like this
`Global multiArray as Variant
'\Now, lots of other functions, when find eligible candidates, add arrays to this array '\like below.
Redim multiarray(len(multiArray)+1)
multiArray(len(multiarray))= newElementArray()
`
So, I end up with something like below. Only that the dimensions will change at runtime, So, I need a generic logic to traverse it.

Let a coordinate represent a location of an element in an n-dimensional array. For example (2,1,3,4) corresponds to an element in position: array[2][1][3][4].
var array = // n-dimensional
function traverse(array, coordinate, dimension);
for(var i = 0 ; i < array.length ; i++){
// assuming coordinate is immutable. Append the current iteration's index.
currentCoordinate = coordinate.add(i);
if(dimension == 1){
doSomething(currentCoordinate, array[i]);
}else{
traverse(array[i], currentCoordinate, dimension(array[i]));
}
}
}
coordinate = []; // at first, the top level coordinate is empty.
traverse(array, coordinate, 4); // 4-dimensional

The implementation will depend on whether it is a multi-dimensional array or a jagged array (array of arrays) as ggreiner shows.
If you only need to traverse the values of the array it can be as simple as:
(C#)
int[, ,] arr = new int[1, 3, 2] { { { 1, 2 }, { 3, 4 }, { 5, 6 } } };
foreach(int i in arr)
Console.WriteLine(i);

Related

design a recursive algorithm that find the minimum of an array

I was thinking about a recursive algorithm (it's a theoretical question, so it's not important the programming language). It consists of finding the minimum of a set of numbers
I was thinking of this way: let "n" be the number of elements in the set. let's rearrange the set as:
(a, (b, c, ..., z) ).
the function moves from left to right, and the first element is assumed as minimum in the first phase (it's, of course, the 0-th element, a). next steps are defined as follows:
(a, min(b, c, ..., z) ), check if a is still minimum, or if b is to be assumed as minimum, then (a or b, min(c, d, ..., z) ), another check condition, (a or b or c, min(d, e, ..., z)), check condition, etc.
I think the theoretical pseudocode may be as follows:
f(x) {
// base case
if I've reached the last element, assume it's a possible minimum, and check if y < z. then return a value to stop recursive calls.
// inductive steps
if ( f(i-th element) < f(i+1, next element) ) {
/* just assume the current element is the current minimum */
}
}
I'm having trouble with the base case. I don't know how to formalize it. I think I've understood the basic idea about it: it's basically what I've written in the pseudocode, right?
does what I've written so far make sense? Sorry if it's not clear but I'm a beginner, and I'm studying recursion for the first time, and I personally find it confusing. So, I've tried my best to explain it. If it's not clear, let me know, and I'll try to explain it better with different words.
Recursive problems can be hard to visualize. Let's take an example : arr = [3,5,1,6]
This is a relatively small array but still it's not easy to visualize how recursion will work here from start to end.
Tip : Try to reduce the size of the input. This will make it easy to visualize and help you with finding the base case. First decide what our function should do. In our case it finds the minimum number from an array. If our function works for array of size n then it should also work for array of size n-1 (Recursive leap of faith). Now using this we can reduce the size of input until we cannot reduce it any further, which should give us our base case.
Let's use the above example: arr = [3,5,1,6]
Let create a function findMin(arr, start) which takes an array and a start index and returns the minimum number from start index to end of array.
1st Iteration : [3,5,1,6]
// arr[start] = 3, If we can somehow find minimum from the remaining array,
// then we can compare it with current element and return the minimum of the two.
// so our input is now reduced to the remaining array [5,1,6]
2nd Iteration : [5,1,6]
// arr[start] = 5, If we can somehow find minimum from the remaining array,
// then we can compare it with current element and return the minimum of the two.
// so our input is now reduced to the remaining array [1,6]
3rd Iteration : [1,6]
// arr[start] = 1, If we can somehow find minimum from the remaining array,
// then we can compare it with current element and return the minimum of the two.
// so our input is now reduced to the remaining array [6]
4th Iteration : [6]
// arr[start] = 6, Since it is the only element in the array, it is the minimum.
// This is our base case as we cannot reduce the input any further.
// We will simply return 6.
------------ Tracking Back ------------
3rd Iteration : [1,6]
// 1 will be compared with whatever the 4th Iteration returned (6 in this case).
// This iteration will return minimum(1, 4th Iteration) => minimum(1,6) => 1
2nd Iteration : [5,1,6]
// 5 will be compared with whatever the 3th Iteration returned (1 in this case).
// This iteration will return minimum(5, 3rd Iteration) => minimum(5,1) => 1
1st Iteration : [3,5,1,6]
// 3 will be compared with whatever the 2nd Iteration returned (1 in this case).
// This iteration will return minimum(3, 2nd Iteration) => minimum(3,1) => 1
Final answer = 1
function findMin(arr, start) {
if (start === arr.length - 1) return arr[start];
return Math.min(arr[start], findMin(arr, start + 1));
}
const arr = [3, 5, 1, 6];
const min = findMin(arr, 0);
console.log('Minimum element = ', min);
This is a good problem for practicing recursion for beginners. You can also try these problems for practice.
Reverse a string using recursion.
Reverse a stack using recursion.
Sort a stack using recursion.
To me, it's more like this:
int f(int[] x)
{
var minimum = head of X;
if (x has tail)
{
var remainder = f(tail of x);
if (remainder < minimum)
{
minimum = remainder;
}
}
return minimum;
}
You have the right idea.
You've correctly observed that
min_recursive(array) = min(array[0], min_recursive(array[1:]))
The function doesn't care about who's calling it or what's going on outside of it -- it just needs to return the minimum of the array passed in. The base case is when the array has a single value. That value is the minimum of the array so it should just return it. Otherwise find the minimum of the rest of the array by calling itself again and compare the result with the head of the array.
The other answers show some coding examples.
This is a recursive solution to the problem that you posed, using JavaScript:
a = [5,12,3,5,34,12]
const min = a => {
if (!a.length) { return 0 }
if (a.length === 1) { return a[0] }
return Math.min(a[0], min(a.slice(1)))
}
min(a)
Note the approach which is to first detect the simplest case (empty array), then a more complex case (single element array), then finally a recursive call which will reduce more complex cases to functions of simpler ones.
However, you don't need recursion to traverse a one dimensional array.

Saving the in-order visit of a binary tree in an array

The question is the following:
is there an algorithm which, given an binary tree T and an array, allows to store in the array the result of the correspondent in-order visit of the tree?
Pseudo-code of a "normal" in-order visit:
inOrder(x){ // x is a node of a binary tree
if(x != NIL){ // the node is not null
inOrder(x.left)
print(x.key)
inOrder(x.right)
}
}
// Function calling inOrder
printInOrder(T){ // T is a binary tree
inOrder(T.root) // T.root is the root of the tree
}
Example:
Given the following tree
5
/ \
3 8
/ \ /
2 7 1
the algorithm above should output 2 3 7 5 1 8.
I'm sure this can be achieved and it shouldn't be too hard but I'm currently struggling for this problem.
Writing to an array (instead of printing) means you need to keep track of which index to write at in the array. If you need to do this without any mutable state other than the array itself, you need to pass the current index as an argument, and return the new current index.
The code below is written in static single assignment form so even the local variables are not mutated. If that isn't required then the code can be simplified a bit. I'm assuming that the array length is known; if it needs to be computed, that is a separate problem.
inOrder(x, arr, i) {
if(x == NIL) {
return i
} else {
i2 = inOrder(x.left, arr, i)
arr[i2] = x.key
i3 = inOrder(x.right, arr, i2 + 1)
return i3
}
}
getArrayInOrder(T, n) {
arr = new array of length n
inOrder(T.root, arr, 0)
return arr
}
First about arrays : In order to populate an array you need to know the length of the array beforehand. If you don't need to specify the length for instantiating an array ( depending on the language that you use ) then that's not really an array. Its a dynamic data structure whose size is increased automatically by the language implementation.
Now I assume you don't know the size of the tree beforehand. If you do know the size, you can instantiate an array of specified size. Assuming you don't know the size of the array, you need to go with a dynamic data structure like ArrayList in Java.
So at each print(x.key) in your code, just append the x.key to the list ( like list.add(x.key) ). After the traversal is complete you may turn your List to array.
You could use iterative version of the traversal too.
One simple solution for recursive approach is to use a single element array to track the index like:
void inOrder(x, int[] idx, int[] arr):
if x != NIL:
inOrder(x.left, idx, arr)
arr[idx[0]++] = x.key
inOrder(x.right, idx, arr)
although I m sure there may be other ways that can become cumbersome (maybe). I prefer iterative version anyway.
If your language / use-case allows putting ints into the array, you could store the index in the array. I'm going backwards because that's simpler then:
inOrder(x, arr){
if(x != NIL){
inOrder(x.right)
arr[--arr[0]] = x.key
inOrder(x.left)
}
}
saveInOrder(T, n){
arr = new int[n]
arr[0] = n
inOrder(T.root, arr)
return arr
}

How to search for the largest subset where every pair meets criteria?

I hope this isn't more of a statistics question...
Suppose I have an interface:
public interface PairValidatable<T>
{
public boolean isValidWith(T);
}
Now if I have a large array of PairValidatables, how do I find the largest subset of that array where every pair passes the isValidWith test?
To clarify, if there are three entries in a subset, then elements 0 and 1 should pass isValidWith, elements 1 and 2 should pass isValidWith, and elements 0 and 2 should pass isValidWith.
Example,
public class Point implements PairValidatable<Point>
{
int x;
int y;
public Point(int xIn, int yIn)
{
x = xIn;
y = yIn;
}
public boolean isValidWith(Point other)
{
//whichever has the greater x must have the lesser (or equal) y
return x > other.x != y > other.y;
}
}
The intuitive idea is to keep a vector of Points, add array element 0, and compare each remaining array element to the vector if it passes the validation with every element in the vector, adding it to the vector if so... but the problem is that element 0 might be very restrictive. For example,
Point[] arr = new Point[5];
arr[0] = new Point(1000, 1000);
arr[1] = new Point(10, 10);
arr[2] = new Point(15, 7);
arr[3] = new Point(3, 6);
arr[4] = new Point(18, 6);
Iterating through as above would give us a subset containing only element 0, but the subset of elements 1, 2 and 4 is a larger subset where every pair passes the validation. The algorithm should then return the points stored in elements 1, 2 and 4. Though elements 3 and 4 are valid with each other and elements 1 and 4 are valid with each other, elements 2 and 3 are not, nor elements 1 and 3. The subset containing 1, 2 and 4 is a larger subset than 3 and 4.
I would guess some tree or graph algorithm would be best for solving this but I'm not sure how to set it up.
The solution doesn't have to be Java-specific, and preferably could be implemented in any language instead of relying on Java built-ins. I just used Java-like pseudocode above for familiarity reasons.
Presumably isValidWith is commutative -- that is, if x.isValidWith(y) then y.isValidWith(x). If you know nothing more than that, you have an instance of the maximum clique problem, which is known to be NP-complete:
Skiena, S. S. "Clique and Independent Set" and "Clique." §6.2.3 and 8.5.1 in The Algorithm Design Manual. New York: Springer-Verlag, pp. 144 and 312-314, 1997.
Therefore, if you want an efficient algorithm, you will have to hope that your specific isValidWith function has more structure than mere commutativity, and you will have to exploit that structure.
For your specific problem, you should be able to do the following:
Sort your points in increasing order of x coordinate.
Find the longest decreasing subsequence of the y coordinates in the sorted list.
Each operation can be performed in O(n*log(n)) time, so your particular problem is efficiently solvable.

Algorithm Help - hit test for small objects

When implementing a selection algorithm in a processing sketch I cycle through each object in the scene and check to see if it is within a few pixel range of where the mouse clicked. There are lots of objects and they are very small.
As you can imagine once the scene gets filled with objects this becomes really burdensome. Are there easy ways to speed up this search? Can I easily I make this search binary? The objects in my scene are points so polygon hit-testing algorithms don't seem like the right solution.
Divide the scene into buckets, either into N x-buckets and M y-buckets, or into N*M x*y buckets. In the former case, the buckets are stored in two arrays (an x-array and a y-array); in the latter case, the buckets are stored in an array of arrays (the outer arrays indexes the x-coordinates, the inner arrays index the y-coordinates). In either case, the buckets store references to all of the points within the area indexed by the bucket; for example, the point (8, 12) would be in the x-bucket [5, 10] and the y-bucket [10, 15], or else it would be in the x*y bucket ([5, 10], [10, 15]).
When looking up a point, either look up the appropriate x and y buckets, or else simply look up the appropriate x*y buckets. In the former case, take intersection(union(x-buckets), union(y-buckets)). You may need to look up multiple buckets depending on the hit radius, for example if you're looking up the x-coordinate 9 with radius 2 then you'd need both the [5, 10] and [10, 15] buckets.
Using separate x and y buckets takes up less space (N + M buckets instead of N*M buckets) and makes the indexing easier (two separate arrays vs. one nested array), while the x*y buckets make for faster lookups since you won't need to take any set intersections.
The smaller your buckets, the more space the data structure will take up, but the fewer false positives you'll retrieve. Ideally, if you have sufficient memory, then the buckets will cover the same interval as the hit radius.
Maybe if you sort the arrays by one axis, lets say x you can speed things by returning early, I got this example from thomas.diewald at processing forum in this question. It may suits your need. Here only the part of the test ( you can look at the comlete code in the link above). There is an ArrayList of point which has x and y fields. Take a look
note that he is using a label for returning.
Arrays.sort(points);
__FIND_NEIGHBORS__:
for (int i = 0; i < num_points; i++) {
Point pi = points[i];
for (int j = i+1; j < num_points; j++) {
Point pj = points[j];
// 1. check in x
float dx = pj.pos.x-pi.pos.x; // always positive -> points are sorted
if( dx > max_dist ){
continue __FIND_NEIGHBORS__; // ... no more points within max_dist.
}
// 2. check in y
float dy = Math.abs(pj.pos.y-pi.pos.y); // not always positive
if( dy > max_dist ){
continue;
}
// 3. check, could also just draw the line here (Manhattan distance)
if ((dx*dx+dy*dy) < max_dist_sq) {
drawLine(pi, pj);
connections++;
}
}
}

Find unique common element from 3 arrays

Original Problem:
I have 3 boxes each containing 200 coins, given that there is only one person who has made calls from all of the three boxes and thus there is one coin in each box which has same fingerprints and rest of all coins have different fingerprints. You have to find the coin which contains same fingerprint from all of the 3 boxes. So that we can find the fingerprint of the person who has made call from all of the 3 boxes.
Converted problem:
You have 3 arrays containing 200 integers each. Given that there is one and only one common element in these 3 arrays. Find the common element.
Please consider solving this for other than trivial O(1) space and O(n^3) time.
Some improvement in Pelkonen's answer:
From converted problem in OP:
"Given that there is one and only one common element in these 3 arrays."
We need to sort only 2 arrays and find common element.
If you sort all the arrays first O(n log n) then it will be pretty easy to find the common element in less than O(n^3) time. You can for example use binary search after sorting them.
Let N = 200, k = 3,
Create a hash table H with capacity ≥ Nk.
For each element X in array 1, set H[X] to 1.
For each element Y in array 2, if Y is in H and H[Y] == 1, set H[Y] = 2.
For each element Z in array 3, if Z is in H and H[Z] == 2, return Z.
throw new InvalidDataGivenByInterviewerException();
O(Nk) time, O(Nk) space complexity.
Use a hash table for each integer and encode the entries such that you know which array it's coming from - then check for the slot which has entries from all 3 arrays. O(n)
Use a hashtable mapping objects to frequency counts. Iterate through all three lists, incrementing occurrence counts in the hashtable, until you encounter one with an occurrence count of 3. This is O(n), since no sorting is required. Example in Python:
def find_duplicates(*lists):
num_lists = len(lists)
counts = {}
for l in lists:
for i in l:
counts[i] = counts.get(i, 0) + 1
if counts[i] == num_lists:
return i
Or an equivalent, using sets:
def find_duplicates(*lists):
intersection = set(lists[0])
for l in lists[1:]:
intersection = intersection.intersect(set(l))
return intersection.pop()
O(N) solution: use a hash table. H[i] = list of all integers in the three arrays that map to i.
For all H[i] > 1 check if three of its values are the same. If yes, you have your solution. You can do this check with the naive solution even, it should still be very fast, or you can sort those H[i] and then it becomes trivial.
If your numbers are relatively small, you can use H[i] = k if i appears k times in the three arrays, then the solution is the i for which H[i] = 3. If your numbers are huge, use a hash table though.
You can extend this to work even if you can have elements that can be common to only two arrays and also if you can have elements repeating elements in one of the arrays. It just becomes a bit more complicated, but you should be able to figure it out on your own.
If you want the fastest* answer:
Sort one array--time is N log N.
For each element in the second array, search the first. If you find it, add 1 to a companion array; otherwise add 0--time is N log N, using N space.
For each non-zero count, copy the corresponding entry into the temporary array, compacting it so it's still sorted--time is N.
For each element in the third array, search the temporary array; when you find a hit, stop. Time is less than N log N.
Here's code in Scala that illustrates this:
import java.util.Arrays
val a = Array(1,5,2,3,14,1,7)
val b = Array(3,9,14,4,2,2,4)
val c = Array(1,9,11,6,8,3,1)
Arrays.sort(a)
val count = new Array[Int](a.length)
for (i <- 0 until b.length) {
val j =Arrays.binarySearch(a,b(i))
if (j >= 0) count(j) += 1
}
var n = 0
for (i <- 0 until count.length) if (count(i)>0) { count(n) = a(i); n+= 1 }
for (i <- 0 until c.length) {
if (Arrays.binarySearch(count,0,n,c(i))>=0) println(c(i))
}
With slightly more complexity, you can either use no extra space at the cost of being even more destructive of your original arrays, or you can avoid touching your original arrays at all at the cost of another N space.
Edit: * as the comments have pointed out, hash tables are faster for non-perverse inputs. This is "fastest worst case". The worst case may not be so unlikely unless you use a really good hashing algorithm, which may well eat up more time than your sort. For example, if you multiply all your values by 2^16, the trivial hashing (i.e. just use the bitmasked integer as an index) will collide every time on lists shorter than 64k....
//Begineers Code using Binary Search that's pretty Easy
// bool BS(int arr[],int low,int high,int target)
// {
// if(low>high)
// return false;
// int mid=low+(high-low)/2;
// if(target==arr[mid])
// return 1;
// else if(target<arr[mid])
// BS(arr,low,mid-1,target);
// else
// BS(arr,mid+1,high,target);
// }
// vector <int> commonElements (int A[], int B[], int C[], int n1, int n2, int n3)
// {
// vector<int> ans;
// for(int i=0;i<n2;i++)
// {
// if(i>0)
// {
// if(B[i-1]==B[i])
// continue;
// }
// //The above if block is to remove duplicates
// //In the below code we are searching an element form array B in both the arrays A and B;
// if(BS(A,0,n1-1,B[i]) && BS(C,0,n3-1,B[i]))
// {
// ans.push_back(B[i]);
// }
// }
// return ans;
// }

Resources