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.
Related
I have a char*. I want to parse it, character by character, and store the location of each in an int*.
With the dummy-string "abbcdc", the content should be as follows
char int*
-------------
'a' -> 0
'b' -> 1,2
'c' -> 3,5
'd' -> 4
I want this to be accessible through a char* containing the entire alphabet, so that each character in the alphabet-pointer points to each separate integer-pointer. This is where I'm lost.
I know I can point to a pointer using the double-asterisk syntax
int **a = &aLocations;
But I don't really know how to refer to the locations-pointer by using a character as a reference. I am pretty new to C, so all pointers (pun intended) are appreciated.
Update 1:
int *aLocations = malloc(3*sizeof(int));
aLocations[0] = 13;
aLocations[1] = 9;
aLocations[2] = 57;
int **a = &aLocations;
This seems to work as expected, but a obviously remains an integer, not a char. I was thinking of writing a function something along the lines of
int *getCharLocations(char c) {
// returns a pointer to the stored character locations
}
but I don't know how to proceed with implementing it.
Ok then.
Although it would be possible it would be pretty ugly and complicated.
So if you do not mind i would suggest to drop char and use integers exclusively.
It is possible since char is in fact just small integer.
So first you would need to create your two dimensional alphabet array:
int *alphabet[26]; // this will create 26 element array of integer pointers
Now we will fill it:
int i = 0;
for(i = 0; i < 26; i++) {
alphabet[i] = malloc(100 * sizeof(int)); //alloc memory for 100 integers (should be enough for human language if we're talking about single words here)
alphabet[i][0] = 'a' + i; // this will put a letter as first element of the array
alphabet[i][1] = 2 // here we will keep index of first available position in our indices array
}
So now we have array like this:
'a', 2, ... // '...' means here that we have space to fill here
'b', 2, ...
...
'z', 2, ...
And you can add indices of occurences of letter to such construction like this:
alphabet[index_of_letter][alphanet[index_of_letter][1]] = index_of_letter; //put index at the end of array
alphabet[index_of_letter][1]++; // increment our index of available position
That's pretty much it.
I didn't test it so it may need some polishing but such approach should do the trick.
PS.
Someone in comments above noted uppercase letters - in such case you would need to extend array to 52 characters to store also occurences of uppercase letters (also fill first element with uppercase letter in for loop for such records). But i guess you will manage from now on
If you have N sorted arrays where possible elements are integers from 0~N-1, and elements in a single array are distinct, how do you check if there are at least two arrays such that at least two elements are common?
For example, if I have following arrays where N = 5:
A[0] = {0},
A[1] = {1, 3},
A[2] = {2},
A[3] = {1, 4},
A[4] = {1, 3}
then A[1] and A[4] both have 1 and 3 in common, and therefore the answer is true.
In other example where N is again 5:
A[0] = {0, 4},
A[1] = {1, 3},
A[2] = {1, 2, 4},
A[3] = {0, 3},
A[4] = {1}
No two arrays A[i], A[j] have at least two elements in common, therefore the answer is false.
It was part of an interview question, which I was only able to solve in O(n^3) time, by iterating through each combination of arrays(A[i], A[j]) and in each iteration I scan from 0 to N-1 to check there are two common elements.
The interviewer indicated that there is a faster solution, and kind of hinted that utilize sortedness of the arrays, but I wasn't able to come up with better solution even if I was thinking of this problem for last 24 hours.
What would be a faster algorithm than O(N^3) to solve this problem?
Thank you.
Create graph with array vertices and number vertices (at most 2N vertices).
Connect every array vertice with its numbers.
If two arrays have a pair of common numbers, there is cycle with length=4 (B-1-C-2 at the picture)
Find if such cycle exists
Both creating graph and searching cycle takes O(N^2)
It's doable in O(n*m) with n = number of elements and m = number of arrays
pointers[m] // one pointer for every array starting at begin();
commons[m][m] = 0 // count commons for every array combination
while(any pointer != end() )
{
find pointer with lowest value;
if any other pointer has this value;
common[x][y] ++; // increment the commons counter for the corresponding arrays
increment chosen pointer;
}
where common[x][y] >= 2 -> arrays contain 2 or more common elements
The algorithm iterates over all arrays "at once" always continuing with the smallest element.
This element is compared to the smallest not visited elements of the other arrays.
If the element are equal a not is taken in the commons array to keep track of the number of common elements.
After every element was visited, you only have to look into the common matrix to see which arrays have more than two common elements.
EDIT: over read something in the question. Sorry
I have an array (1D), and other array of same size in different order (which will change according to the program situation) should also have the same value.
For example:
array1 = {1,2,3,4,5};
hence array2, should automatically have,
array2 = {4,2,3,1,5};
Some what you can say, i want to jumble up values according to my unique reference. But whenever parent array1 changes, array2 should also be updated at its respective indexes. Is it even possible? Array memory mapping? looping and saving to other array is taking time as this operation is iterated several times. I cannot do memcpy, because order can be different. Any pointers/helps/suggestions will be appreciated.
There's no magical way to do this. What you need to do is store the actual values somewhere, and then access them through a permutation stored separately. Here's some example code that uses strings so the permutation and the values are clearly distinct:
char *strings[] = {"foo", "bar", "baz", "quux"};
size_t memory_order[] = {0, 1, 2, 3};
size_t sorted_order[] = {1, 2, 0, 3};
// Get the k'th element in the memory order:
strings[memory_order[k]];
// Get the k'th element in the sorted order:
strings[sorted_order[k]];
Not directly, no. C doesn't specify a way to do that (which makes sense to me, since most computers don't either, and C tends to be fairly close to the metal).
The typical way to solve it is to manually do the re-mapping, of course:
static const size_t map1to2[] = { 3, 1, 2, 0, 4 };
Then do the accesses to array2 through the remap:
printf("array2[3] is %d\n", array1[map1to2[3]]);
This maps the index 3 to 0, and thus prints 1.
You can use macros to make it slightly more managable.
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].
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);
}
}
}
}
}