Recreate a binary matrix with least "XOR" operations - java

This was a highschool-degree coding contest question a while back. The basic idea was to recreate a painting of black and white with only rectangular XOR operations, or that's what they called it.
The problem
Let us assume we have this painting we are trying to recreate (represented as a binary matrix, 0 being black and 1 being white):
1 0 0
1 1 1
1 0 1
One way of recreating the painting would be the following operations:
(0, 0) (2, 2)
(1, 0) (2, 0)
(1, 2) (1, 2)
The operations are in the form of (xStart, yStart) (xEnd, yEnd)
Thus the above operations would do the following, if we start from an all-black canvas:
beginning:
0 0 0
0 0 0
0 0 0
after (0, 0) (2, 2) :
1 1 1
1 1 1
1 1 1
after (1, 0) (2, 0) :
1 0 0
1 1 1
1 1 1
after (1, 2) (1, 2) :
1 0 0
1 1 1
1 0 1
Technicalities about the assignment:
Winner has the least operations.
One operation should be in the form of (xStart, yStart) (xEnd, yEnd).
There are no time or space restraints.
In the assignment, the painting we were trying to recreate was 200x200 in size, and generated with 2000 random XOR operations.
My own ideas
I have come up with a couple of ways to do this. I'll list them here in order of worse to best.
XOR all the pixels:
We can recreate the painting by simply writing 1 to a blank canvas where a 1 resides in the painting we are trying to recreate. This solution is the simplest and most obvious of all. The number of operations needed is basically the amount of white pixels in the painting.
XOR all horizontally adjacent whites:
This is a substantial improvement from the first solution, but still very simple and obvious. In this method we simply XOR all horizontally adjacent whites. In this way, for example the operations
(0, 0) (0, 0)
(1, 0) (1, 0)
(2, 0) (2, 0)
would be diminished to (0, 0) (2, 0).
XOR rectangles:
This I think is a clear follow-up of the previous method, which we can see as XORing rectangles with height of 1 - Now we just add a second dimension to the rectangles, further improving our results. I determined the XORable area by getting the rectangle with the most whites. The improvement is still good.
XOR the biggest difference:
This is a slight change from the above methods, and a bit more brute-force. In this method I find the rectangle with the biggest difference to the painting, and XOR it. For example, if we have the painting
1 0 1
0 1 1
0 1 0
and an all-black canvas, the biggest difference would be in the rectangle (0, 0) (2, 1), which has a difference of 2. I calculate the difference by getting all the non-same colors of the painting, which is 4 in the above situation, and then subtracting the amount of same colors from it, which in the above situation is 2. So different_colors - same_colors = difference.
In the above painting and a blank canvas, there are many rectangles that produce the same difference. One other is (1, 0) (2, 2).
This method gave the smallest improvement from the previous one with large paintings, but an improvement nonetheless. Interstingly, this method sometimes came up with a worse solution than the previous one with small paintings (can't remember how small, though).
Any code I had for the described methods above have been long since lost. Can you come up with breath-taking solutions? Is there a magical approach from outer space? I find this question (post) pretty interesting and would like to see if anyone can come up with anything.
About the tags
I have tagged this with both Java and C++, not because this question concerns particularly those languages, but because I can easily understand any code written in those languages, and with languages with similar syntax.

I think, to complete this task, we require to find the coordinates of maximum size sub-matrix containing only zeros.
I can explain that algorithm but I think following link has the best explanation :
Maximum size sum-matrix with all 1s in binary matrix
Here solution is for all 1s, we can modify it for all 0s.
Then all we need to do is find the coordinate from maximum value and we can do operation.
I'll update if I can think of some better method.

Related

About how to divide a list relatively evenly

I have a list. I need to divide it into 4 groups, and the sum of each group is relatively average. The list can be sorted or not.
Give an example: list(1,1,4,2,2,3,5,6) -> Divide into (1,1,4), (2,2,3), (5), (6).
Thanks in advance here, I know this requires some algorithmic ability.
You have three things to play with here.
a set of numbers, no of segments and the average of each segment.
If two of these are set, the third is automatically set.
In your case, your set of numbers is pre-defined and the no of segments is predefined - hence the average is also pre-defined.
You need to find this average and then run through the numbers. If the segments are required to be contiguous as in your example, this is the only way to do this.
If the elements in the segment can be non contiguous, then there are a lot more possibilities and your chances of getting to an even distribution is also better. You can keep a track of the four segments and add to whatever segment seems to be furthest away from it's target average. This is a greedy way to do this.
Keep in mind that your array could be horribly skewed.
Say the average is 6 and your array looks like
{ 24 , 0 , 0 , 0 , 0 ,0 , 0 , 0}
The ONLY distribution possible here would be
{24} ,{ 0 } , {0 , 0 ,0 },{0 , 0 ,0 }
Perhaps find the average of each group like so: (1+1+4+2+2+3+5+6)/4=6 and keep track of the total sum of each group. If it is in a certain [allowable] range, say 1 or 2, then proceed to the next list.

Calling an Array within a program (java)

I'm currently putting together a basic world viewer program. At each viewpoint, I have 4 pictures, each at 90 degrees to one another. I have created an array of photos for each viewpoint and an String currentPoint which will hold the name of the viewpoint. I think there is a way to take the name of the current array and call the contents of it so I need only write one set of code for the turn left ad turn right functions below, but I can't think what it would be. How is it done?
Suppose that your array array is arranged in the order [north-facing, east-facing, south-facing, west-facing], and that you have an index i indicating the index of the current view (0 for north, 1 for east, 2 for south, 3 for west). Then to "turn left" is to decrement i modulo 4 and to "turn right" is to increment i modulo 4.
With this approach, turning right is straightforward: i = (i + 1) % 4.
Turning left is a little bit tricker, because % is actually defined as a remainder operator in Java, rather than as a modulus operator, so i = (i - 1) % 4 will not work (it will leave i == -1 when it should be i == 3). Instead, you can write: i = (i + 3) % 4.
(With this in mind, we can define a full set of absolute directional constants — NORTH as 0, EAST as 1, SOUTH as 2, WEST as 3 — and relative directional constants — FRONT as 0, RIGHT as 1, BACK as 2, LEFT as 3. Then, for example, WEST == (NORTH + LEFT) % 4 and NORTH == (WEST + RIGHT) % 4.)

Optimal merging of triplets

I'm trying to come up with an algorithm for the following problem :
I've got a collection of triplets of integers - let's call these integers A, B, C. The value stored inside can be big, so generally it's impossible to create an array of size A, B, or C. The goal is to minimize the size of the collection. To do this, we're provided a simple rule that allows us to merge the triplets :
For two triplets (A, B, C) and (A', B', C'), remove the original triplets and place the triplet (A | A', B, C) if B == B' and C = C', where | is bitwise OR. Similar rules hold for B and C also.
In other words, if two values of two triplets are equal, remove these two triplets, bitwise OR the third values and place the result to the collection.
The greedy approach is usually misleading in similar cases and so it is for this problem, but I can't find a simple counterexample that'd lead to a correct solution. For a list with 250 items where the correct solution is 14, the average size computed by greedy merging is about 30 (varies from 20 to 70). The sub-optimal overhead gets bigger as the list size increases.
I've also tried playing around with set bit counts, but I've found no meaningful results. Just the obvious fact that if the records are unique (which is safe to assume), the set bit count always increases.
Here's the stupid greedy implementation (it's just a conceptual thing, please don't regard the code style) :
public class Record {
long A;
long B;
long C;
public static void main(String[] args) {
List<Record> data = new ArrayList<>();
// Fill it with some data
boolean found;
do {
found = false;
outer:
for (int i = 0; i < data.size(); ++i) {
for (int j = i+1; j < data.size(); ++j) {
try {
Record r = merge(data.get(i), data.get(j));
found = true;
data.remove(j);
data.remove(i);
data.add(r);
break outer;
} catch (IllegalArgumentException ignored) {
}
}
}
} while (found);
}
public static Record merge(Record r1, Record r2) {
if (r1.A == r2.A && r1.B == r2.B) {
Record r = new Record();
r.A = r1.A;
r.B = r1.B;
r.C = r1.C | r2.C;
return r;
}
if (r1.A == r2.A && r1.C == r2.C) {
Record r = new Record();
r.A = r1.A;
r.B = r1.B | r2.B;
r.C = r1.C;
return r;
}
if (r1.B == r2.B && r1.C == r2.C) {
Record r = new Record();
r.A = r1.A | r2.A;
r.B = r1.B;
r.C = r1.C;
return r;
}
throw new IllegalArgumentException("Unable to merge these two records!");
}
Do you have any idea how to solve this problem?
This is going to be a very long answer, sadly without an optimal solution (sorry). It is however a serious attempt at applying greedy problem solving to your problem, so it may be useful in principle. I didn't implement the last approach discussed, perhaps that approach can yield the optimal solution -- I can't guarantee that though.
Level 0: Not really greedy
By definition, a greedy algorithm has a heuristic for choosing the next step in a way that is locally optimal, i.e. optimal right now, hoping to reach the global optimum which may or may not be possible always.
Your algorithm chooses any mergable pair and merges them and then moves on. It does no evaluation of what this merge implies and whether there is a better local solution. Because of this I wouldn't call your approach greedy at all. It is just a solution, an approach. I will call it the blind algorithm just so that I can succinctly refer to it in my answer. I will also use a slightly modified version of your algorithm, which, instead of removing two triplets and appending the merged triplet, removes only the second triplet and replaces the first one with the merged one. The order of the resulting triplets is different and thus the final result possibly too. Let me run this modified algorithm over a representative data set, marking to-be-merged triplets with a *:
0: 3 2 3 3 2 3 3 2 3
1: 0 1 0* 0 1 2 0 1 2
2: 1 2 0 1 2 0* 1 2 1
3: 0 1 2*
4: 1 2 1 1 2 1*
5: 0 2 0 0 2 0 0 2 0
Result: 4
Level 1: Greedy
To have a greedy algorithm, you need to formulate the merging decision in a way that allows for comparison of options, when multiple are available. For me, the intuitive formulation of the merging decision was:
If I merge these two triplets, will the resulting set have the maximum possible number of mergable triplets, when compared to the result of merging any other two triplets from the current set?
I repeat, this is intuitive for me. I have no proof that this leads to the globally optimal solution, not even that it will lead to a better-or-equal solution than the blind algorithm -- but it fits the definition of greedy (and is very easy to implement). Let's try it on the above data set, showing between each step, the possible merges (by indicating the indices of triplet pairs) and resulting number of mergables for each possible merge:
mergables
0: 3 2 3 (1,3)->2
1: 0 1 0 (1,5)->1
2: 1 2 0 (2,4)->2
3: 0 1 2 (2,5)->2
4: 1 2 1
5: 0 2 0
Any choice except merging triplets 1 and 5 is fine, if we take the first pair, we get the same interim set as with the blind algorithm (I will this time collapse indices to remove gaps):
mergables
0: 3 2 3 (2,3)->0
1: 0 1 2 (2,4)->1
2: 1 2 0
3: 1 2 1
4: 0 2 0
This is where this algorithm gets it differently: it chooses the triplets 2 and 4 because there is still one merge possible after merging them in contrast to the choice made by the blind algorithm:
mergables
0: 3 2 3 (2,3)->0 3 2 3
1: 0 1 2 0 1 2
2: 1 2 0 1 2 1
3: 1 2 1
Result: 3
Level 2: Very greedy
Now, a second step from this intuitive heuristic is to look ahead one merge further and to ask the heuristic question then. Generalized, you would look ahead k merges further and apply the above heuristic, backtrack and decide the best option. This gets very verbose by now, so to exemplify, I will only perform one step of this new heuristic with lookahead 1:
mergables
0: 3 2 3 (1,3)->(2,3)->0
1: 0 1 0 (2,4)->1*
2: 1 2 0 (1,5)->(2,4)->0
3: 0 1 2 (2,4)->(1,3)->0
4: 1 2 1 (1,4)->0
5: 0 2 0 (2,5)->(1,3)->1*
(2,4)->1*
Merge sequences marked with an asterisk are the best options when this new heuristic is applied.
In case a verbal explanation is necessary:
Instead of checking how many merges are possible after each possible merge for the starting set; this time we check how many merges are possible after each possible merge for each resulting set after each possible merge for the starting set. And this is for lookahead 1. For lookahead n, you'd be seeing a very long sentence repeating the part after each possible merge for each resulting set n times.
Level 3: Let's cut the greed
If you look closely, the previous approach has a disastrous perfomance for even moderate inputs and lookaheads(*). For inputs beyond 20 triplets anything beyond 4-merge-lookahead takes unreasonably long. The idea here is to cut out merge paths that seem to be worse than an existing solution. If we want to perform lookahead 10, and a specific merge path yields less mergables after three merges, than another path after 5 merges, we may just as well cut the current merge path and try another one. This should save a lot of time and allow large lookaheads which would get us closer to the globally optimal solution, hopefully. I haven't implemented this one for testing though.
(*): Assuming a large reduction of input sets is possible, the number of merges is
proportional to input size, and
lookahead approximately indicates how much you permute those merges.
So you have choose lookahead from |input|, which is
the binomial coefficient that for lookahead ≪ |input| can be approximated as
O(|input|^lookahead) -- which is also (rightfully) written as you are thoroughly screwed.
Putting it all together
I was intrigued enough by this problem that I sat and coded this down in Python. Sadly, I was able to prove that different lookaheads yield possibly different results, and that even the blind algorithm occasionally gets it better than lookahead 1 or 2. This is a direct proof that the solution is not optimal (at least for lookahead ≪ |input|). See the source code and helper scripts, as well as proof-triplets on github. Be warned that, apart from memoization of merge results, I made no attempt at optimizing the code CPU-cycle-wise.
I don't have the solution, but I have some ideas.
Representation
A helpful visual representation of the problem is to consider the triplets as points of the 3D space. You have integers, so the records will be nodes of a grid. And two records are mergeable if and only if the nodes representing them sit on the same axis.
Counter-example
I found an (minimal) example where a greedy algorithm may fail. Consider the following records:
(1, 1, 1) \
(2, 1, 1) | (3, 1, 1) \
(1, 2, 1) |==> (3, 2, 1) |==> (3, 3, 1)
(2, 2, 1) | (2, 2, 2) / (2, 2, 2)
(2, 2, 2) /
But by choosing the wrong way, it might get stuck at three records:
(1, 1, 1) \
(2, 1, 1) | (3, 1, 1)
(1, 2, 1) |==> (1, 2, 1)
(2, 2, 1) | (2, 2, 3)
(2, 2, 2) /
Intuition
I feel that this problem is somehow similar to finding the maximal matching in a graph. Most of those algorithms finds the optimal solution by begining with an arbitrary, suboptimal solution, and making it 'more optimal' in each iteration by searching augmenting paths, which have the following properties:
they are easy to find (polynomial time in the number of nodes),
an augmenting path and the current solution can be crafted to a new solution, which is strictly better than the current one,
if no augmenting path is found, the current solution is optimal.
I think that the optimal solution in your problem can be found in the similar spirit.
Based on your problem description:
I'm given a bunch of events in time that's usually got some pattern.
The goal is to find the pattern. Each of the bits in the integer
represents "the event occurred in this particular year/month/day". For
example, the representation of March 7, 2014 would be [1 <<
(2014-1970), 1 << 3, 1 << 7]. The pattern described above allows us to
compress these events so that we can say 'the event occurred every 1st
in years 2000-2010'. – Danstahr Mar 7 at 10:56
I'd like to encourage you with the answers that MicSim has pointed at, specifically
Based on your problem description, you should check out this SO
answers (if you didn't do it already):
stackoverflow.com/a/4202095/44522 and
stackoverflow.com/a/3251229/44522 – MicSim Mar 7 at 15:31
The description of your goal is much more clear than the approach you are using. I'm scared that you won't get anywhere with the idea of merging. Sounds scary. The answer you get depends upon the order that you manipulate your data. You don't want that.
It seems you need to keep data and summarize. So, you might try counting those bits instead of merging them. Try clustering algorithms, sure, but more specifically try regression analysis. I should think you would get great results using a correlation analysis if you create some auxiliary data. For example, if you create data for "Monday", "Tuesday", "first Monday of the month", "first Tuesday of the month", ... "second Monday of the month", ... "even years", "every four years", "leap years", "years without leap days", ... "years ending in 3", ...
What you have right now is "1st day of the month", "2nd day of the month", ... "1st month of the year", "2nd month of the year", ... These don't sound like sophisticated enough descriptions to find the pattern.
If you feel it is necessary to continue the approach you have started, then you might treat it more as a search than a merge. What I mean is that you're going to need a criteria/measure for success. You can do the merge on the original data while requiring strictly that A==A'. Then repeat the merge on the original data while requiring B==B'. Likewise C==C'. Finally compare the results (using the criteria/measure). Do you see where this is going? Your idea of bit counting could be used as a measure.
Another point, you could do better at performance. Instead of double-looping through all your data and matching up pairs, I'd encourage you to do single passes through the data and sort it into bins. The HashMap is your friend. Make sure to implement both hashCode() and equals(). Using a Map you can sort data by a key (say where month and day both match) and then accumulate the years in the value. Oh, man, this could be a lot of coding.
Finally, if the execution time isn't an issue and you don't need performance, then here's something to try. Your algorithm is dependent on the ordering of the data. You get different answers based on different sorting. Your criteria for success is the answer with the smallest size after merging. So, repeatedly loop though this algorithm: shuffle the original data, do your merge, save the result. Now, every time through the loop keep the result which is the smallest so far. Whenever you get a result smaller than the previous minimum, print out the number of iterations, and the size. This is a very simplistic algorithm, but given enough time it will find small solutions. Based on your data size, it might take too long ...
Kind Regards,
-JohnStosh

recursive game plan function

I want to write a simple recursive function for a game plan in java.
I have 2^k teams and want an output like this (e.g. 4 teams):
(team)(day1)(day2)(day3)
1 2 3 4
2 1 4 3
3 4 1 2
4 3 2 1
My idea was to call the function recursive with half of its original size, but I can't figure out how to code it properly. If called with n/2, the output has to go into the upper left corner of the plan, the output PLUS n/2 has to go to the lower left corner and the rest is symmetric to the center.
Thanks
My code so far
public void plan(int size) {
if(size==2){}
else{}
}
make a Set for each day (unique)
then use n(max number)
itterate a loop n times and each itteration
newRandomNumber % n (fetch a random number a limit it to 0 to (n-1)
now add the (generatedValue+1) to the set
if it already exists (do check ) then increment the value till its new value then add to set
note: i dont get ur symetric requirement

2D collision detection of images with transparent parts ignored

So I decided to look up some collision detection but I've been having trouble finding proper information
regarding 2d collision detection between two images that includes how to properly avoid detecting the transparent
areas of an image but I did find one post which I got myself attached to but the problem is that I don't
really understand the post nor do I understand why he does some of those things...
Here's the post in question: https://stackoverflow.com/posts/336615/revisions
So first of all I want to ask if this solution is actually a good one / proper or if I should just look elsewhere.
Secondly I wonder, in his post, he mentions using integer arrays, not 2d arrays either it seems, to
set 1 and 0 to decide whether or not the pixel is transparent or not but I don't really know how I am supposed
to achieve this. At first I thought it could be achieved by just forming a string of 1 and 0s and convert it to a Long
but even with a mere image width of 25, the Long, gets... too long...
I also tried this with no luck, since the code does not function with this array:
long[] array = new long[30*30]; // height * width of the image
int x = 0;
int y = 0;
for(int i = 0; i<30*30; i++){
if(image.getRGB(x,y) == 0){
array[i] = 0;
}
else{ array[i] = 1; }
x++;
if (x==30){
y++;
x=0;
}
}
Thirdly, I was hoping someone could maybe explain the whole process and why the things he does, are necessary.
By the way, I do know how those bit wise operators work!
In other words, I don't understand his train of thought / motivation for doing the all things in the code and I would like to gain an understanding of all this!
I don't really know how to proceed right now hehe...
The result of the bitwise AND operation (&) is true (1) for each each bit where the the corresponding bit is true in both operands, and false (0) otherwise.
The idea he's using is to create a version of the image (a mask) where each non-transparent pixel in the original image is stored as a '1' bit, and each transparent pixel as a '0' bit. These are packed into a single integer, which can be tested against the mask for another image with a single AND operation (before the AND he calculates the horizontal distance between the two images and shifts one of the masks if necessary).
For example, let's assume that we have the following two 4x1 pixel images:
5, 0, 0, 5
8, 8, 8, 8
Although I placed them on separate rows here for practical purposes, you should view them as being on the same row, so the last two pixels of the left image overlap with the first two of the right image.
The masks for the rows when viewed in binary representation would be:
1001
1111
The distance between the left and right image is -2, so we shift the first mask left by 2 bits:
1001 << 2 => 100100
So now we have these masks:
100100
001111
ANDing these gives us:
000100
The non-zero result tells us that we have a collision.

Categories