Any ideas on how to solve this matrix / 2x2D array computation? - c

I have 2 3x3 matrices each represented in 2D arrays.
First matrix holds elements [ I store PID so,the range of elements could be from millions Iam just simplifying it as A in my actual application it is an integer range A could be 200 and B could be 200000]
e.g., matrix element
{ A B C
B D C
C F B }
second holds weight of each location
e.g., Matrix weight
{ 9 7 5
8 6 1
7 5 4 }
so in the above example B is the heaviest element because its weight is 7+8+4 followed by C etc.,
How do I find out the top 3 highest element ?
One solution is:
Is to store the elements in a separate array A[9][2]( element, value and unique) looping the element matrix and then another loop to go through the value array and filling up the value corresponding to the element.
[ iterate to create a 9x2 key value matrix,iterate to sort, iterate to remove duplicates(since weights need to be consolidated ), - Is there a better way ? ]
Any other efficient way ? [hint : I need only 3 so i shouldnt use 9x2 ]

Let's assume you know you have only letters A-Z available and they are capitals.
char elems[3][3] = {
{ 'A', 'B', 'C' },
{ 'B', 'D', 'C' },
{ 'C', 'F', 'B' }
};
And you have similarly set up your weights...
You can keep track of counts like this:
int counts[26] = {0};
for( int i = 0; i < 3; i++ ) {
for( int j = 0; j < 3; j++ ) {
counts[elems[i][j] - 'A'] += weights[i][j];
}
}
Then it's just a case of finding the index of the three largest counts, which I'm sure you can do easily.

Forget that they're 2D arrays, and merge the two data sources into a single array (of pairs). For your example, you would get {{'A', 9}, {'B', 7}, {'C', 5}, {'B', 8}, ...}. Sort these (for example, with qsort), and then scan through the list, summing as you go -- and maintaining the top 3 scored keys you find.
[This solution always works, but only makes sense if the arrays are large, which on re-reading the question they're not].

Related

Compiling multiple reverse permutations

sorry if this isn't an appropriate question for here, it's just been melting my mind the last few hours and I'm sure I'm missing something obvious!
I've got a system set up which swaps the order of a series of entries in an array multiple times. For this I'm just using a Fisher-Yates swapping algorithm to create a corresponding array which where the corresponding index entry is to be moves to.
So what I want to be able to do is go back multiple steps. At the moment I'm trying to figure out the way of writing how I'd be able to get back from the second swap to the original order in a dynamically produced array using the two information from the swap arrays. I assume once I'm able to build one which goes back two steps in one go that I just keep applying the same approach to go back another step.
What would be the easiest approach of building an array of {'a','b','c','d'} using exclusively the information of swap[0], swap[1] and arr[1]?
The code below is pretty much pseudocode, everything is working fine in the actual program asides from generating the reverse permutation thing.
char theOriginal[4] = {'a', 'b', 'c', 'd'}; //the initial order
int swap[x][4];
char arr[x][4];
/*below code would actually be generated using functions*/
swap[0] = GetSwap(4); //eg. returns {2,3,0,1} generated using a Fisher-Yates swap
arr[0] = Swappit(theOriginal, swap[0]); //returns {'c', 'd', 'a', 'b'} permuted array produced by function which rearranged theOriginal's values to correspond with swap[0]
//all entries after the first one built in a loop
for(z=1; z<x; z++){
swap[z] = GetSwap(4); //e.g. return {1,3,2,0} another permutation built the same way
arr[z] = Swappit(arr[z-1], swap[z]); //from swap[z] applied to arr[0], we get {'d','b','a','c'}
}
If that code is too confusingly worded to give an answer to easily, here's a more stripped down one you can use:
char letters[4] = {'a', b', 'c', 'd'};
int move1[4] = {2, 3, 0, 1};
char reorder1[4] = {'c', 'd', 'a', 'b'};
int move2[4] = {1, 3, 2, 0};
char reorder2[4] = {'d', 'b', 'a', 'c'};
/**something happens here so that using move1 and move2,
a new integer array can be built which will give a third
reordering which matches letters, ie the follow outputs**/
int moveBack[4] = {2, 1, 3, 0};
char reorderBack = {'a', 'b', 'c', 'd'};
You simply have to compute the inverse permutation for each step and apply them in reverse order.
If you have a forward permutation P defined as
moveP[0] = n0
moveP[1] = n1
moveP[2] = n2
moveP[3] = n3
then you compute the corresponding inverse permutation P-1 such as
movePinv[n0] = 0
movePinv[n1] = 1
movePinv[n2] = 2
movePinv[n3] = 3
That way you have P-1(Y) = X if P(X) = Y.
In your example, if you start from array A0 and apply 2 permutations P and Q, giving the steps A1 = P(A0) and A2 = Q(A1) = Q(P(A0)), then to get back the initial array A0, you have to apply the inverse permutations in reverse order to the final array. That is A1 = Q-1(A2) then A0 = P-1(A1) = P-1(Q-1(A2)).
Note that for an improved memory usage you can definitely do this incrementally, accumulating all the inverse permutations in a single one (assuming you are only interested in retrieving the initial order but not the intermediate steps of course).
Edit : following your code, here is what the backward step could look like to. It's clearly not great if you plan to do it several times (since the inverse permutations would be computed and applied to the source array each time), but for a one-shot, it's the simplest way.
int backFrom = x - 1, backTo = 0; // for example
char state[4] = arr[backFrom];
int swapInvAux[4];
for (z = backFrom; z >= backTo; --z)
{
swapInvAux = InversePermutation(swap[z]);
state = Swappit(state, swapInvAux);
}
For better performance, parallel to the swap array you should store a chain of accumulated inverse permutations obtained by applying your Swappit function to the swap array itself. Doing so you would be able to reverse the final state to any intermediate state in a single step.

Calculating indexes in a filtered array

Suppose I have an array A = {a,b,c,d,e,f,g} and a set of (zero-based) indexes I={1,3,5} in A. Now suppose that I actually don't have A, but only the array which is the result of removing the indexes specified in I from A, i.e. B = {a,c,e,g} (I also have I itself).
Given an index in B, can I analytically calculate the corresponding index in A? For example, for the index 3 in B the answer should be 6.
It's easy to think of a O(|A|) solution, but it's unacceptable as A can get pretty big. A O(|I|) solution should be fine. Also note that I may periodically change (more indexes removed).
Perhaps use an array that for each of the elements in B would have the number of elements before that index that were removed {0,1,2,3} then one would take the index into B and look up in that array and add that value to the index into B to get the index into A. This would take additional space equal to the size of B but would be O(1).
"I" splits original array into some slices. We can get B concatenating these slice. With I={1,3,5} we get slices {0, 0}, {2,2}, {4,4}, {6,lastA} We can create an ordered map where the keys are indices in B and the values are slices.
{ 0: {0,0}, 1: {2, 2}, 2: {4, 4}, 3: {6,lastA} }
Actually, we don't need to keep upper bound of each slice
{ 0: 0, 1: 2, 2: 4, 3: 6 }
In C++ code make look like this:
std::function<size_t (size_t)> getIndexConverter(size_t sizeOfA, std::vector<size_t> I)
{
std::map<size_t, size_t> abIndices;
size_t sliceStart = 0;
for (size_t i = 0, imax = I.size(); i < imax; ++i) {
if (sliceStart < I[i])
abIndices.emplace(sliceStart - i, sliceStart);
sliceStart = I[i] + 1;
}
if (sliceStart < sizeOfA)
abIndices.emplace(sliceStart - I.size(), sliceStart);
return [abIndices](size_t bIndex) -> size_t {
auto slice = abIndices.lower_bound(bIndex);
assert(slice != abIndices.end()); // it is impossible because of algorithm we use to construct abIndices
return bIndex - slice->first + slice->second;
};
}
full example on Ideone
This method requires additional memory equal to number of slices and executes with logarithmic time.

Printing all possible words from a 2D array of characters

Stumbled upon this interview question recently,
Given a 2-dimensional array of characters and a dictionary in which a word can be searched in O(1) time. Need to print all the words from array which are present in dictionary. Word can be formed in any direction but has to end at any edge of array.(Need not worry much about the dictionary)
Input:
a f h u n
e t a i r
a e g g o
t r m l p
Output:
after
hate
hair
air
eat
tea
Note: Here "egg" is not a dictionary word because its not ending at the edge of array.
I've seen similar questions before, but was never able to think of a good algorithm to solve these kind of problems. Any help on how to approach these kind of problems (forming words from arrays of characters) will be highly helpful.
(The only way I could think of is to find all possible permutations of characters in the 2D array, and check if it ends on the edge of the array, and check if the permutation is a valid word from the dictionary in O(1) time)
Turn the array into a graph so that each cell [i,j]
has an edge shared with each one of its 4 neighbors [i+1,j], [i-1,j], [i,j+1], [i,j-1].
Then run DFS at each array-edge-cell and and keep checking the dictionary whether
the word in reverse is in it.
You did not mention anything about a character can be used only once - so without this restriction is problem of "Can we generate k (or more) different words?" is undecideable.1.
(With a constraint on the number of "visites" per element there are finite number of possibilities and the claim and proof does not hold of course).
Proof:
It is known that there is no algorithm A that can decide if a terminating algorithm B returns true for k or more different inputs. (will look for citation for this claim later if needed, trust me for now).
We will show that given an algorithm A that says if there are k or more generated words - we can decide if there are k or more different inputs that yield "true":
Let the (terminating) algorithm that decides if there are k or
more generated words be M.
Without loss of generality - assume binary alphabet (we can represent everything with it).
Let:
array = 0 1
0 1
Note we can generate any binary word while walking on this array.
Algorithm A:
input: algorithm B, natural number n
output: true if and only if algorithm B answers "true" for n or more different inputs.
The algorithm:
(1) use B(word) as the black box dictionary - if the answer is true, then word is in dictionary.
(2) use array as the array.
(3) Run M on (array,dictionary,n), and answer like it.
Note that if M answered true -> there are n or more accepted words -> there are n or more different inputs to B that yields true (definition of dictionary and since we can generate every input with array) -> the answer to the problem is true.
(if the algorithm answered false the proof is similar).
QED
Conclusion:
If we can repeat a character in the array more then a once (or to be exact - unbounded number of times) - then the problem is unsolveable without any information on the dictionary.
(1) An undecideble problem is a problem where there is no algorithm that can answer TRUE/FALSE correctly in 100% of the cases - For every algorithm, there is some case where the algorithm will get "stuck" in an infinite loop (or give a wrong answer). The most common of "undecideable" problems is the Halting Problem - which says - there is no algorithm A that can take any algorithm B and answer if B stops for some input w.
My solution is:
I suppose that I have an M*N array and there is no restriction in searching words. For example 'rood' and 'door' are 2 different words as being reversed of each other.
Start from the first letter (left, top). In this case, it is 'a'. And check adjacents if there are any words in dictionary(suppose there are words starting with 'ae' and 'af' ) Check whether they are already words or not and the index of the last letter is 0 or M-1 or N-1. If not, add them to a queue to look later. By turns, check all queued substrings like this and finish this this phase by prosessing all values in queue. Then check second letter and go on up to the last member of array. Like this, you will be able to check all possible words.
It works on one of my problems like this but Im not sure if you are looking also for complexity.
import java.util.HashSet;
import java.util.Set;
/**
* Given a 2-dimensional array of characters and a
* dictionary in which a word can be searched in O(1) time.
* Need to print all the words from array which are present
* in dictionary. Word can be formed in any direction but
* has to end at any edge of array.
* (Need not worry much about the dictionary)
*/
public class DictionaryWord {
private static char[][] matrix = new char[][]{
{'a', 'f', 'h', 'u', 'n'},
{'e', 't', 'a', 'i', 'r'},
{'a', 'e', 'g', 'g', 'o'},
{'t', 'r', 'm', 'l', 'p'}
};
private static int dim_x = matrix.length;
private static int dim_y = matrix[matrix.length -1].length;
private static Set<String> wordSet = new HashSet<String>();
public static void main(String[] args) {
//dictionary
wordSet.add("after");
wordSet.add("hate");
wordSet.add("hair");
wordSet.add("air");
wordSet.add("eat");
wordSet.add("tea");
for (int x = 0; x < dim_x; x++) {
for (int y = 0; y < dim_y; y++) {
checkAndPrint(matrix[x][y] + "");
int[][] visitedMap = new int[dim_x][dim_y];
visitedMap[x][y] = 1;
recursion(matrix[x][y] + "", visitedMap, x, y);
}
}
}
private static void checkAndPrint(String word) {
if (wordSet.contains(word)) {
System.out.println(word);
}
}
private static void recursion(String word, int[][] visitedMap, int x, int y) {
for (int i = Math.max(x - 1, 0); i < Math.min(x + 2, dim_x); i++) {
for (int j = Math.max(y - 1, 0); j < Math.min(y + 2, dim_y); j++) {
if (visitedMap[i][j] == 1) {
continue;
} else {
int[][] newVisitedMap = new int[dim_x][dim_y];
for (int p = 0; p < dim_x; p++) {
for (int q = 0; q < dim_y; q++) {
newVisitedMap[p][q] = visitedMap[p][q];
}
}
newVisitedMap[i][j] = 1;
checkAndPrint(word + matrix[i][j]);
recursion(word + matrix[i][j], newVisitedMap, i, j);
}
}
}
}
}

All Possible combinations in C

I'm trying to find a efficient algorithm in C, which provides me all combinations of a given charset.
The algorithm should not recursive. At last the number of digits should be flexible. For example:
char set[] = "a1";
->
a1
aa
1a
11
I've only found a Perl solution, but it uses substr(). I think that wasn't that fast performance-wise.
For most algorithms in C, I've found were only permutations...
A article in a german C++ forum claims, that C++-STL Solutions are faster than "raw" recursive algorithms.
If the set size were a fixed N it would be simple - you could just have N for loops, each one nested into the previous one. Since you can't do this and you can't use recursion, you have to calculate the total required number of iterations (seems like it's N^M), use one single loop and then use / and % to calculate what the array index of each character should be. You'd better use longs as well, because N^M gets big fast.
Wikipedia has C code for the n-ary Gray code. It should be convertible to your problem by using the digits as offsets into your input array. You will need to do some dynamic allocation to handle the arbitrary length of your input. A related approach is to do nested loops, where you have an array of loop counters as long as your input, and another counter for which of those you are currently incrementing. E.g. printing all six-digit base-six numbers, needs to be modified for dynamic allocation but shows the principle:
int i;
int length = 5;
int max = 6;
int counters[length];
for (i=0; i<length; i++)
counters[i] = 0;
for(;;) {
for (i=length-1; i>=0; i--)
printf("%d", counters[i]);
printf("\n");
for(i=0; i<length; i++) {
counters[i]++;
if (counters[i] < max)
break;
else
counters[i] = 0;
}
if (i >= length)
break;
}
Python is very close to a pseudo code.
You can read the Python source to itertools.permutations and just replicate in C.
Here is the demo that this works:
#!/usr/bin/env python
import itertools
s='a1'
print set(itertools.permutations(s*len(s), len(s)))
Output:
set([('1', '1'), ('a', '1'), ('a', 'a'), ('1', 'a')])
Here is an even simpler way:
>>> s='a1'
>>> ['{}{}'.format(x,y) for x in s for y in s]
['aa', 'a1', '1a', '11']
>>> s='abc'
>>> ['{}{}{}'.format(x,y,z) for x in s for y in s for z in s]
['aaa', 'aab', 'aac', 'aba', 'abb', 'abc', 'aca', 'acb',
'acc', 'baa', 'bab', 'bac', 'bba', 'bbb', 'bbc', 'bca',
'bcb', 'bcc', 'caa', 'cab', 'cac', 'cba', 'cbb', 'cbc',
'cca', 'ccb', 'ccc']
To unwind a list comprehension, use NESTED LOOPS, like so:
>>> for x in s:
... for y in s:
... for z in s:
... print '{}{}{}'.format(x,y,z)
Well, I would number the possible combinations, loop through the numbers and convert.
For instance: to generate all size 3 combinations of the 10 symbols {'0', '1', ..., '9'}, I would loop from 0 to 999 and output "000" to "999".
In the same way (kinda), to generate all size 3 combinations of the 5 symbols {'a', 'b', ..., 'e'} I would loop from 0 to 5*5*5-1 and output the loop number in base 5, but with the symbols provided.
Write a function that will convert an integer into a string hexadecimal number, then convert that algorithm into a base 36 (a-z plus 0-9) number. Use one for loop to count from 1 to (digit count times base) and call your function each time.
1 becomes 1
10 becomes a
35 becomes z
36 becomes 10
46 becomes 1a

Interleave array in constant space

Suppose we have an array
a1, a2,... , an, b1, b2, ..., bn.
The goal is to change this array to
a1, b1, a2, b2, ..., an, bn in O(n) time and in O(1) space.
In other words, we need a linear-time algorithm to modify the array in place, with no more than a constant amount of extra storage.
How can this be done?
This is the sequence and notes I worked out with pen and paper. I think it, or a variation, will hold for any larger n.
Each line represents a different step and () signifies what is being moved this step and [] is what has been moved from last step. The array itself is used as storage and two pointers (one for L and one for N) are required to determine what to move next. L means "letter line" and N is "number line" (what is moved).
A B C D 1 2 3 4
L A B C (D) 1 2 3 4 First is L, no need to move last N
N A B C (3) 1 2 [D] 4
L A B (C) 2 1 [3] D 4
N A B 1 (2) [C] 3 D 4
L A (B) 1 [2] C 3 D 4
N A (1) [B] 2 C 3 D 4
A [1] B 2 C 3 D 4 Done, no need to move A
Note the varying "pointer jumps" - the L pointer always decrements by 1 (as it can not be eaten into faster than that), but the N pointer jumps according to if it "replaced itself" (in spot, jump down two) or if it swapped something in (no jump, so the next something can get its go!).
This problem isn't as easy as it seems, but after some thought, the algorithm to accomplish this isn't too bad. You'll notice the first and last element are already in place, so we don't need to worry about them. We will keep a left index variable which represents the first item in the first half of the array that needs changed. After that we set a right index variable to the first item in the 2nd half of the array that needs changed. Now all we do is swap the item at the right index down one-by-one until it reaches the left index item. Increment the left index by 2 and the right index by 1, and repeat until the indexes overlap or the left goes past the right index (the right index will always end on the last index of the array). We increment the left index by two every time because the item at left + 1 has already naturally fallen into place.
Pseudocode
Set left index to 1
Set right index to the middle (array length / 2)
Swap the item at the right index with the item directly preceding it until it replaces the item at the left index
Increment the left index by 2
Increment the right index by 1
Repeat 3 through 5 until the left index becomes greater than or equal to the right index
Interleaving algorithm in C(#)
protected void Interleave(int[] arr)
{
int left = 1;
int right = arr.Length / 2;
int temp;
while (left < right)
{
for (int i = right; i > left; i--)
{
temp = arr[i];
arr[i] = arr[i - 1];
arr[i - 1] = temp;
}
left += 2;
right += 1;
}
}
This algorithm uses O(1) storage (with the temp variable, which could be eliminated using the addition/subtraction swap technique) I'm not very good at runtime analysis, but I believe this is still O(n) even though we're performing many swaps. Perhaps someone can further explore its runtime analysis.
First, the theory: Rearrange the elements in 'permutation cycles'. Take an element and place it at its new position, displacing the element that is currently there. Then you take that displaced element and put it in its new position. This displaces yet another element, so rinse and repeat. If the element displaced belongs to the position of the element you first started with, you have completed one cycle.
Actually, yours is a special case of the question I asked here, which was: How do you rearrange an array to any given order in O(N) time and O(1) space? In my question, the rearranged positions are described by an array of numbers, where the number at the nth position specifies the index of the element in the original array.
However, you don't have this additional array in your problem, and allocating it would take O(N) space. Fortunately, we can calculate the value of any element in this array on the fly, like this:
int rearrange_pos(int x) {
if (x % 2 == 0) return x / 2;
else return (x - 1) / 2 + n; // where n is half the size of the total array
}
I won't duplicate the rearranging algorithm itself here; it can be found in the accepted answer for my question.
Edit: As Jason has pointed out, the answer I linked to still needs to allocate an array of bools, making it O(N) space. This is because a permutation can be made up of multiple cycles. I've been trying to eliminate the need for this array for your special case, but without success.. There doesn't seem to be any usable pattern. Maybe someone else can help you here.
It's called in-place in-shuffle problem. Here is its implementation in C++ based on here.
void in_place_in_shuffle(int arr[], int length)
{
assert(arr && length>0 && !(length&1));
// shuffle to {5, 0, 6, 1, 7, 2, 8, 3, 9, 4}
int i,startPos=0;
while(startPos<length)
{
i=_LookUp(length-startPos);
_ShiftN(&arr[startPos+(i-1)/2],(length-startPos)/2,(i-1)/2);
_PerfectShuffle(&arr[startPos],i-1);
startPos+=(i-1);
}
// local swap to {0, 5, 1, 6, 2, 7, 3, 8, 4, 9}
for (int i=0; i<length; i+=2)
swap(arr[i], arr[i+1]);
}
// cycle
void _Cycle(int Data[],int Lenth,int Start)
{
int Cur_index,Temp1,Temp2;
Cur_index=(Start*2)%(Lenth+1);
Temp1=Data[Cur_index-1];
Data[Cur_index-1]=Data[Start-1];
while(Cur_index!=Start)
{
Temp2=Data[(Cur_index*2)%(Lenth+1)-1];
Data[(Cur_index*2)%(Lenth+1)-1]=Temp1;
Temp1=Temp2;
Cur_index=(Cur_index*2)%(Lenth+1);
}
}
// loop-move array
void _Reverse(int Data[],int Len)
{
int i,Temp;
for(i=0;i<Len/2;i++)
{
Temp=Data[i];
Data[i]=Data[Len-i-1];
Data[Len-i-1]=Temp;
}
}
void _ShiftN(int Data[],int Len,int N)
{
_Reverse(Data,Len-N);
_Reverse(&Data[Len-N],N);
_Reverse(Data,Len);
}
// perfect shuffle of satisfying [Lenth=3^k-1]
void _PerfectShuffle(int Data[],int Lenth)
{
int i=1;
if(Lenth==2)
{
i=Data[Lenth-1];
Data[Lenth-1]=Data[Lenth-2];
Data[Lenth-2]=i;
return;
}
while(i<Lenth)
{
_Cycle(Data,Lenth,i);
i=i*3;
}
}
// look for 3^k that nearnest to N
int _LookUp(int N)
{
int i=3;
while(i<=N+1) i*=3;
if(i>3) i=i/3;
return i;
}
Test:
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int length = sizeof(arr)/sizeof(int);
in_place_in_shuffle(arr, length);
After this, arr[] will be {0, 5, 1, 6, 2, 7, 3, 8, 4, 9}.
If you can transform the array into a linked-list first, the problem becomes trivial.

Resources