I have 3 lists: ListOfBoxes, ListOfGoals and ListOfDoned.
these first 2 lists contain transforms, the 3rd is empty.
When a box from ListOfBoxes x and z position are the same as a goals in ListOfGoals i move that box to ListOfDoned.
What I want to happen next is; If a box in the ListOfDoned is no longer at a goal in ListOfGoals move back into ListOfBoxes.
Here Is My Code:
for(var n = 0; n < ListOfGoals.Count; n++)
{
for (var p = 0; p < ListOfBoxes.Count; p++)
{
if (Mathf.Abs(ListOfBoxes[p].position.x - ListOfGoals[n].position.x) < epsilon)
{
if (Mathf.Abs(ListOfBoxes[p].position.z - ListOfGoals[n].position.z) < epsilon)
{
Debug.Log("Box" + p + " has been placed at " + n);
ListOfDoned.Add(ListOfBoxes[p]);
ListOfBoxes.RemoveAt (p);
break;
}
}
}
}
for (var q = 0; q < ListOfDoned.Count; q++)
{
for (r = 0; r < ListOfGoals.Count; r++)
{
if (Mathf.Abs(ListOfDoned[q].position.x - ListOfGoals[r].position.x) < epsilon)
{
if (Mathf.Abs(ListOfDoned[q].position.z - ListOfGoals[r].position.z) < epsilon)
{
break;
}
else
{
if (r == ListOfGoals.Count)
{
ListOfBoxes.Add(ListOfDoned[q]);
ListOfDoned.RemoveAt (q);
}
}
}
}
}
I can see that what is happening is that it's checking all of the goals in the list instead of exiting if it has found one, but I'm not sure what the logic would be go get this working correctly.
Thanks in advance.
[EDIT to try to add clarity] - Imagine I have 2 boxes in ListOfBoxes and 2 goals in listofgoals. When 1 box moves to the same position as one of the goals (only x and z axis, not y) I want that box removed from ListOfBoxes to ListOfDoned. That's the first nested for loop, and it seems to be working fine. However if that box is later moved from the same position as one of those goals I need it back in ListOfBoxes. This is what I want the second nested for loop to do.
What appears to be happening is that it is comparing the boxes in listOfDoned with all of the goals in listofgoals and (even though it has the same position as one of the goals) it doesnt have the same position as the other one so the else case and put the box in the list listofboxes.
I need to check against the position of all the goals, and as long as it's position is the same as one of them, don't do anything, else return it to listOfBoxes.
[EDIT: This answer addresses what I believe is a problem in your code, but I don't think it fixes the behaviour you describe in your comments. Let me revise this pending more clarification.]
I believe the problem you describe is due to your if statement inside the second nested loop:
if (r == ListOfGoals.Count)
{
ListOfBoxes.Add(ListOfDoned[q]);
ListOfDoned.RemoveAt (q);
}
You need to remember that the contents of your loop will only execute if the condition you specified in your for loop is true. In this case, that is
r < ListOfGoals.Count
This means that your if condition r == ListOfGoals.Count can never occur, because the loop will terminate before r ever reaches up to ListOfGoals.Count. Since the condition never evaluates to true, items will never be moved from ListOfDoned to ListOfBoxes, even if they're supposed to be.
To fix this, I suggest changing your if statement to:
if (r == ListOfGoals.Count - 1)
{
ListOfBoxes.Add(ListOfDoned[q]);
ListOfDoned.RemoveAt (q);
}
Which would correspond to the last execution of the loop. Hope this helps! Let me know if you have any questions.
Thanks to PipsqueakGames on twitter for helping me reach this solution.
for(var n = 0; n < ListOfGoals.Count; n++)
{
for (var p = 0; p < ListOfBoxes.Count; p++)
{
if (Mathf.Abs(ListOfBoxes[p].position.x - ListOfGoals[n].position.x) < epsilon)
{
if (Mathf.Abs(ListOfBoxes[p].position.z - ListOfGoals[n].position.z) < epsilon)
{
Debug.Log("Box" + p + " has been placed at " + n);
ListOfDoned.Add(ListOfBoxes[p]);
ListOfBoxes.RemoveAt (p);
break;
}
}
}
}
for (q = 0; q < ListOfDoned.Count; q++)
{
var matched:boolean = false;
for (r = 0; r < ListOfGoals.Count; r++)
{
if (Mathf.Abs(ListOfDoned[q].position.x - ListOfGoals[r].position.x) < epsilon)
{
if (Mathf.Abs(ListOfDoned[q].position.z - ListOfGoals[r].position.z) < epsilon)
{
matched = true;
Debug.Log("Box" + q + " is still at " + r);
break;
}
}
}
if (!matched)
{
ListOfBoxes.Add(ListOfDoned[q]);
ListOfDoned.RemoveAt (q);
}
}
Related
I'm doing training tasks from codility. I am done with StoneWall with 100/100 rate but I'm stuck with the main idea of Manhattan skyline problem in that task. The task is described here https://app.codility.com/programmers/task/stone_wall/
Well when I read that problem the first time, i realized that I should just calculate minimum number of stone blocks to build the wall. There are no any explanations about how blocks can be extended and so on.(Probably assumptions include that I have to know it in advance. But I had never worked with such a problem). Based on my understanding of this problem I implemented the next algorithm(As it's turned out the incorrect one)
public int solution(final int[] H)
{
if (H.length == 1)
{
return 1;
}
int blocks = 0;
int first = 0;
for (int i = 1; i <= H.length; i++)
{
if (i == H.length || H[first] > H[i])
{
for (int k = first; k < i; k++)
{
if (H[k] != 0)
{
for (int t = k + 1; t < i && H[k] <= H[t]; t++)
{
if (H[t] >= H[k])
{
H[t] = H[t] - H[k];
}
else
{
break;
}
}
blocks++;
}
}
first = i;
}
}
return blocks;
}
Above code works fine for simple little arrays. For example { 8, 8, 5, 7, 9, 8, 7, 4, 8 }. Obviously it failed performance. I wanted to run this to understand that i'm in correct way. But it returns incorrect results for e.g. large array with values within 1...20. The problem is that I don't understand the main idea of the building wall process so I cannot replicate it on my local.
Then I researched a little bit and found this solution on codility https://codility.com/media/train/solution-stone-wall.pdf It's saying that
The intuition is that by extending each stone block to the ground, we obtain a set of
buildings forming the given skyline.
I thought that it was a clue.(I should just stack smaller blocks on top of bigger ones.) But then I took a look at the figures with possible arrangements of blocks and it confused me again.
2.
Finally I implemented it using the second picture above and it works good(100% on codility)
public int solution2(final int[] H)
{
if (H.length == 1)
{
return 1;
}
int blocks = 0;
final ArrayDeque<Integer> stack = new ArrayDeque<Integer>();
stack.push(H[0]);
for (int i = 1; i < H.length; i++)
{
while (stack.size() > 0 && stack.peek() > H[i])
{
stack.pop();
blocks++;
}
if (stack.isEmpty() || stack.peek() < H[i])
{
stack.push(H[i]);
}
}
return blocks + stack.size();
}
Could someone explain me please why the first algorithm doesn't work for this task?
bool binsearch(int x) {
int i = 0, j = N;
while(i < j) {
int m = (i+j)/2;
if(arr[m] <= x) {
if(arr[m] == x)
return true;
i = m+1;
}
else {
j = m;
}
}
return false;
}
This is my implementation of binary search which returns true if x is in arr[0:N-1] or
returns false if x is not in arr[0:N-1].
And I'm wondering how can I figure out right loop invariant to prove this implementation is correct.
How can I solve this problem?
Thanks a lot :D
Think about the variables holding state within your loop. In your case, they are variables i and j. You start with the fact that all elements < i and less than the value you are searching for (x) and all elements > j and greater than the x. This is the invariant you are trying to maintain.
I have a couple of questions I couldn't find online regarding Shell sort with Shell's gap.
public static void shell(int[] a) {
int increment = a.length / 2;
while (increment > 0) {
for (int i = increment; i < a.length; i++) {
int j = i;
int temp = a[i];
while (j >= increment && a[j - increment] > temp) {
a[j] = a[j - increment];
j = j - increment;
}
a[j] = temp;
}
if (increment == 2) {
increment = 1;
} else {
increment *= (5.0 / 11);
}
}
}
This is the code I found online, but I don't really understand the last else statement. What does 5.0/11 represent?
Also I need to analyse the complexity of the algorithm, though I'm receiving pretty perplexing results:
It seems that it is O(n) either best and worst cases. Are these results legit?
5.0/11 is actually used to get the half of the increment. Anything <0.5 and >0.45 will work to obtain the half of the value in round figures.
I came across this interview questions. It says we have to do a binary search on a sorted array. Following is the code for that. This code has bug such that it doesn't give right answer. You have to change the code to give correct output.
Condition : You are not allowed to add line and you can change only three lines in the code.
int solution(int[] A, int X) {
int N = A.length;
if (N == 0) {
return -1;
}
int l = 0;
int r = N;
while (l < r) {
int m = (l + r) / 2;
if (A[m] > X) {
r = m - 1;
} else {
l = m+1;
}
}
if (A[r] == X) {
return r;
}
return -1;
}
I tried a lot on my own but was missing on some test cases.
I hate this question, it's one of those "unnecessary constraint" questions. As others have mentioned, the problem is that you're not returning the value if you find it. Since the stupid instructions say you can't add any code, you can hack it like this:
if (A[m] >= X) {
r = m;
} else {
l = m;
}
This kills the performance but it should work.
You need to check for the searched value inside the loop, for exit if it's found
Sample Code:
int solution(int[] A, int X) {
int N = A.length;
if (N == 0) {
return -1;
}
int l = 0;
int r = N;
while (l <= r) { // change here, need to check for the element if l == r
// this is the principal problem of your code
int m = (l + r) / 2;
if (A[m] == X) { // new code, for every loop check if the middle element
return r; // is the search element for early exit.
} else if (A[m] > X) {
r = m - 1;
} else {
l = m + 1;
}
}
return -1;
}
Other problem is that you are testing more elements that you need when the element is in the array.
Try this:
int l = 0;
int r = N - 1; // changed
while (l <= r) { // changed
You have to understand the method that is used. You are looking for the first element >= X.
You want k with i < k <=> A[i] < X.
L is for left. It is the lower limit for k. You have i < l => A[i] < X.
R is for right. It is the upper limit for k. You have i >= r => A[i] >= X.
Your target is to reduce the range and have l = r. To do so you check the value in the middle, at m = (r+l)/2.
If A[m] >= X then m satisfies the conditions for r. You can set r = m.
If A[m] < X then A[m] belongs to the part left of l. So you can set l to the right of m, l = m+1.
Each loop reduces the range between l and r. When you reach l==r, you have found the point I called k. A[k] is the smallest number >= X. You only need to check if it is == X or > X.
From there you should be able to fix the code.
PS: Note that the k (aka l or r) can be >= A.length. You need to verify that.
I put this code in the draw() function in Processing, and it doesn't work. Can someone explain why, and help me fix this? What I want it to do is to cycle through each element of the 2d boolean array and check if it is true or false.
for(int i = 0; i < elemts.length; i++)
{
for(int j = 0; j < elemts[0].length; j++)
{
if(elemts[i][j] == true)
{
rect(i*5,j*5,5,5);
}
}
}
The for loop should be like this
for(start; condition; code to excute every turn)
When you want to skip it you should add a semicolon.
First of all, you didn't add i++ or j++, so the for-loop doesn't run. Next, the draw function runs itself 60 times per second, so putting a for-loop with a certain number of elements doesn't allow the draw() to work. Use the below code instead.
if(elemts[x][y] == true)
{
rect(x*5,y*5,5,5);
fill(0,0,0);
}
if(x < elemts.length)
{
x += 1;
}
if(x == elemts.length)
{
x = 0;
y += 1;
}