Java AVL Tree Problems - java

I'm trying to build an AVL tree in Java, but I'm having trouble with updating heights after the rotations. Here is the code I'm having trouble with.
public void checkHeights(Node<T> u) {
if (u == nil) return;
checkHeights(u.left);
checkHeights(u.right);
System.out.println(u.h);
if (height(u) != 1 + Math.max(height(u.left), height(u.right)))
throw new RuntimeException("Check heights shows incorrect heights");
int dif = height(u.left) - height(u.right);
if (dif < -1 || dif > 1)
throw new RuntimeException("Check heights found height difference of " + dif);
}
/**
* Fix up
* #param u
*/
public void fixup(Node<T> u) {
while (u != nil) {
int dif = height(u.left) - height(u.right);
if(debug)System.out.println("Node dif at " + u.x + " is: " + dif);
if (dif > 1) {
if(debug)System.out.println("u.left is larger");
if(height(u.left.left) - height(u.left.right) < 0) {
if(debug)System.out.println("u.left dif is: " + (height(u.left.left) - height(u.left.right)));
rotateLeft(u.left);
}
rotateRight(u);
} else if (dif < -1) {
if(debug)System.out.println("u.right is larger");
if(height(u.right.left) - height(u.right.right) > 0) {
if(debug)System.out.println("u.right dif is: " + (height(u.right.left) - height(u.right.right)));
rotateRight(u.right);
}
rotateLeft(u);
}
if(debug) System.out.println("Height of " + u.x + " is " + height(u));
u = u.parent;
}
}
public void rotateLeft(Node<T> u) {
super.rotateLeft(u);
u.h = Math.max(height(u.left), height(u.right)) + 1;
u.parent.h = Math.max(height(u.parent.left), height(u.parent.right)) + 1;
if(debug)System.out.println("After left rotation, " + u.x + " has height " + u.h + " and " + u.parent.x + " has height " + u.parent.h);
}
public void rotateRight(Node<T> u) {
super.rotateRight(u);
u.h = Math.max(height(u.left), height(u.right)) + 1;
u.parent.h = Math.max(height(u.parent.left), height(u.parent.right)) + 1;
if(debug)System.out.println("After right rotation, " + u.x + " has height " + u.h + " and " + u.parent.x + " has height " + u.parent.h);
}
I've done a bunch of unit tests, and I keep getting checkHeights throwing exceptions. I'm almost positive that what's going on is the when a rotation occurs at a depth greater than 2, the heights aren't updated recursively up the tree. For example, if I add values from 0 to 10 in, the first left rotation occurs no problem and the values get their right heights, but when I try to rotate lower down, the parent nodes aren't accurately update to their new heights, causing the exceptions to be thrown.
Any help would be greatly appreciated

Related

ARCore: Get the 3D coordinates of all detected points

I’m programming an app for point cloud detection with ARCore in Java.
I want to get the 3D coordinates of all points, which are rendered in the frames. Currently I get only a very few of these points, if I use the following code.
pointCloud = frame.acquirePointCloud();
if (list1 != null) {
String x = String.valueOf(df.format(pointCloud.getPoints().get(0))).replace(",", ".");
String y = String.valueOf(df.format(pointCloud.getPoints().get(1))).replace(",", ".");
String z = String.valueOf(df.format(pointCloud.getPoints().get(2))).replace(",", ".");
String c = String.valueOf(df.format(pointCloud.getPoints().get(3))).replace(",", ".");
list1.add(x + ", " + y + ", " + z + ", " + c + "\n");
}
I only found one other implementation. I tried this one, but I got a lot of confusing points, which drifted away.
pointCloud = frame.acquirePointCloud();
if (list6 != null) {
FloatBuffer fb = pointCloud.getPoints();
while (fb.hasRemaining()) {
float x = Float.parseFloat(df.format(fb.get()).replace(",", "."));
float y = Float.parseFloat(df.format(fb.get()).replace(",", "."));
float z = Float.parseFloat(df.format(fb.get()).replace(",", "."));
float c = Float.parseFloat(df.format(fb.get()).replace(",", "."));
list6.add(x + ", " + y + ", " + z + ", " + c + "\n");
}
}
I´m not sure that it is a problem in the code.
Does sombody have a better idea to get all points or can tell me what I’m doing wrong?
I would be glad about some help. Thanks.
I have used this code for acquiring Point Cloud data. You can check the length of Point Cloud Ids array to know the exact number of Point Clouds.
Using the below code you can map the Point Data to exact ID and be sure if all the data is available.
PointCloud pointCloud = frame.acquirePointCloud();
IntBuffer pointCloudIds = pointCloud.getIds();
int[] pointCloudIdsArray = new int[pointCloudIds.limit()];
pointCloudIds.get(pointCloudIdsArray);
Log.i(TAG, "onDrawFrame: Point Cloud Id Array Length " +
pointCloudIdsArray.length);
FloatBuffer pointCloudData = pointCloud.getPoints();
float[] pointCloudArray = new float[pointCloudData.limit()];
pointCloudData.get(pointCloudArray);
Log.i(TAG, "onDrawFrame: Point Cloud Data Array Length " + pointCloudArray.length);
long PointCloudTimeStamp = pointCloud.getTimestamp();
if (pointCloudIdsArray.length > 0) {
for (int i = 0; i < pointCloudIdsArray.length; i++) {
Log.i("TAG",Long.toString(PointCloudTimeStamp) + ";" +
Integer.toString(pointCloudIdsArray[i]) + ";" +
Float.toString(pointCloudArray[i * 4]) + ";" +
Float.toString(pointCloudArray[i * 4 + 1]) + ";" +
Float.toString(pointCloudArray[i * 4 + 2]) + ";" +
Float.toString(pointCloudArray[i * 4 + 3]) + "\n");
}
}

Trying to mimic Splitwise app logic - suggest a better way to handle settlements

I am trying to write the basic logic used in apps like Splitwise.
Input - Transactions in the trip
a|a,b,c,d|120
b|a,b,d|210
c|a,b,c,d|40
a|a,b,c|60
a, b, c and d are friends on a trip
in the first transaction a paid 120 units for a transaction involving all four friends
in the second transaction b paid 210 units for a transaction involving only a, b and d
there are n such transactions and there can be m friends
Expected Output
a has to get 50
b has to get 80
c has to give 20
d has to give 110
d has to give 80 to b
d has to give 30 to a
c has to give 20 to a
This is what I tried. Person class is the pojo used.
public class Person {
private String name;
private Integer totalExpense;
private Integer totalSpent;
private Integer balanceAmt;
}
This is the code for settle operation.
public void settle(Map<String, Person> personMap) {
List<Person> getterList = new ArrayList<>();
List<Person> giversList = new ArrayList<>();
for (String key : personMap.keySet()) {
Person user = personMap.get(key);
int balanceAmt = user.getTotalSpent() - user.getTotalExpense();
user.setBalanceAmt(Math.abs(balanceAmt));
if (balanceAmt > 0) {
System.out.println(key + " has to get " + balanceAmt);
getterList.add(user);
} else if (balanceAmt < 0) {
System.out.println(key + " has to give " + Math.abs(balanceAmt));
giversList.add(user);
} else if (balanceAmt == 0) {
System.out.println(key + " is all settled");
}
}
getterList.sort((p2, p1) -> p1.getBalanceAmt().compareTo(p2.getBalanceAmt()));
giversList.sort((p2, p1) -> p1.getBalanceAmt().compareTo(p2.getBalanceAmt()));
giversList.forEach(giver -> {
getterList.forEach(getter -> {
if (getter.getBalanceAmt() == 0) {
return;
}
if (giver.getBalanceAmt() == getter.getBalanceAmt()) {
System.out.println(giver.getName() + " has to give " + giver.getBalanceAmt() + " to " + getter.getName());
giver.setBalanceAmt(0);
getter.setBalanceAmt(0);
} else if (giver.getBalanceAmt() > getter.getBalanceAmt()) {
System.out.println(giver.getName() + " has to give " + getter.getBalanceAmt() + " to " + getter.getName());
giver.setBalanceAmt(giver.getBalanceAmt() - getter.getBalanceAmt());
getter.setBalanceAmt(0);
} else if (giver.getBalanceAmt() < getter.getBalanceAmt()) {
System.out.println(giver.getName() + " has to give " + giver.getBalanceAmt() + " to " + getter.getName());
giver.setBalanceAmt(0);
getter.setBalanceAmt(getter.getBalanceAmt() - giver.getBalanceAmt());
}
});
});
}
The code is not good, it has too many loops.
Suggest a good method to settle the amount and come up with the second part of the output.
Reduce your bottom part's logic from O(m2) to O(m) by using two pointer.
int giverPointer = 0;
int getterPointer = 0;
while(giverPointer < giversList.size() && getterPointer < getterList.size()){
if (giversList.get(giverPointer).getBalanceAmt() == getterList.get(getterPointer).getBalanceAmt()) {
System.out.println(giversList.get(giverPointer).getName() + " has to give " + giversList.get(giverPointer).getBalanceAmt() + " to " + getterList.get(getterPointer).getName());
giversList.get(giverPointer).setBalanceAmt(0);
getterList.get(getterPointer).setBalanceAmt(0);
giverPointer++;
getterPointer++;
} else if (giversList.get(giverPointer).getBalanceAmt() > getterList.get(getterPointer).getBalanceAmt()) {
System.out.println(giversList.get(giverPointer).getName() + " has to give " + getterList.get(getterPointer).getBalanceAmt() + " to " + getterList.get(getterPointer).getName());
giversList.get(giverPointer).setBalanceAmt(giversList.get(giverPointer).getBalanceAmt() - getterList.get(getterPointer).getBalanceAmt());
getterList.get(getterPointer).setBalanceAmt(0);
getterPointer++;
} else {
System.out.println(giversList.get(giverPointer).getName() + " has to give " + giversList.get(giverPointer).getBalanceAmt() + " to " + getterList.get(getterPointer).getName());
giversList.get(giverPointer).setBalanceAmt(0);
getterList.get(getterPointer).setBalanceAmt(getterList.get(getterPointer).getBalanceAmt() - giversList.get(giverPointer).getBalanceAmt());
giverPointer++;
}
}

logic error? diving 2 int that result in a float

I am writing a combat simulator. My attacker class initiates an attack and my defender class is supposed to block it. manager is my main class that computes and prints the results. My problem is with my highRatio, mediumRatio and lowRatio variables. If they are not equal to 1 all of them are set to zero. Any ideas as to what may be going?
//defender class
public int defenseSelector(int highAtkCounter, int mediumAtkCounter, int lowAtkCounter, int rounds, int roundCounter)
{
Random defenseTypeGenerator;
int defense = 0;
float highRatio;
float mediumRatio;
float lowRatio;
defenseTypeGenerator = new Random();
int defenseType = defenseTypeGenerator.nextInt(MAX_ROUNDS) + 1;
highRatio = highAtkCounter/roundCounter;
mediumRatio = mediumAtkCounter/roundCounter;
lowRatio = lowAtkCounter/roundCounter;
if(roundCounter > 3 && roundCounter <= rounds) //AI portion
{
if (highRatio > mediumRatio && highRatio > lowRatio)
{
defense = HIGH;
}
else if (mediumRatio > highRatio && mediumRatio > lowRatio)
{
defense = MEDIUM;
}
else if (lowRatio > highRatio && lowRatio > mediumRatio)
{
defense = LOW;
}
else
{
System.out.println("AI ERROR ratios " + highRatio + " " + mediumRatio + " " + lowRatio);
System.out.println("AI ERROR atkCounters " + highAtkCounter + " " + mediumAtkCounter + " " + lowAtkCounter);
System.out.println("AI ERROR rCounters " + roundCounter);
//manager class
while(roundCounter <= rounds)
{
int attack = theAttacker.attackSelector(high, medium, low);
int highAtkTracker = theAttacker.countHighAtks(attack);
System.out.println("DEBUG " + attack);
System.out.println("DEBUG " + highAtkTracker);
int mediumAtkTracker = theAttacker.countMediumAtks(attack);
System.out.println("DEBUG " + attack);
System.out.println("DEBUG " + mediumAtkTracker);
int lowAtkTracker = theAttacker.countLowAtks(attack);
System.out.println("DEBUG " + attack);
System.out.println("DEBUG " + lowAtkTracker);
highAtkCounter = highAtkCounter + highAtkTracker;
mediumAtkCounter = mediumAtkCounter + mediumAtkTracker;
lowAtkCounter = lowAtkCounter + lowAtkTracker;
int defense = theDefender.defenseSelector(highAtkCounter, mediumAtkCounter, lowAtkCounter, rounds, roundCounter);
In java any arithmetic operation with an integer results in an integer.
Therefore you must cast the integer into the floating point type explicitly:
highAtkCounter = highAtkCounter + (float)highAtkTracker;
mediumAtkCounter = mediumAtkCounter + (float)mediumAtkTracker;
lowAtkCounter = lowAtkCounter + (float)lowAtkTracker;

Java Math.random won't refresh on while loop (of course)

So, I am trying to make a text based RPG. A good starter project, as I am new to all of this. I want to make a critical hit, and math.random seems like the best way to go. Only one problem; when it loops, it doesn't refresh the random. I can assume that that's because it calls it once, and once it's called in, that's it. That's it's value. I want to know of an alternative so it refreshes every time the while loop starts over. I know there are some other bugs in my code; but that's not what I'm focusing on right now. Here's the entire method:
public void battleStart(Enemy enemy, Player player)
{
while (enemy.health != 0)
{
String battle = null;
int criticalHt = (int) (Math.random() * 10) + 0;
boolean T = true;
while (T = true)
{
battle = Game.console.next();
enemy.attackplayer(player);
if (battle.toLowerCase().contains("skip"))
{
System.out.println(criticalHt);
if (criticalHt == 1)
{
player.hitPoints -= enemy.dmg * 2;
System.out.println(Game.toTitleCase(enemy.firstName) + " " + Game.toTitleCase(enemy.lastName) + " has used " + Game.toTitleCase(enemy.attackName) + " for a critical level of " + enemy.dmg * 2 + "!.\n Your health is now " + player.hitPoints + ".");
}
else
{
player.hitPoints -= enemy.dmg;
System.out.println(Game.toTitleCase(enemy.firstName) + " " + Game.toTitleCase(enemy.lastName) + " has used " + Game.toTitleCase(enemy.attackName) + ".\n Your health is now " + player.hitPoints + ".");
System.out.println("Your turn to attack! Use an attack, or type \"skip\" to let your enemy strike.");
};
if (battle.contains("skp"))
{
};
}
}
}
Move the code
int criticalHt = (int)(Math.random() * 10) + 0;
INSIDE the while loop
while(T = true){
int criticalHt = (int)(Math.random() * 10) + 0;
battle = Game.console.next();
...

Deleting last new line string

So I've tried pretty much everything to get rid of the last newline character in my code. Its supposed to print a new line after every recursive call except for the last one. Any ideas?
public static boolean solve(double target, ArrayList<Double> numbers)
{
String print = "";
String newPrint = "";
double compare = 0;
boolean done = false;
for (double num : numbers)
{
if (!done)
{
ArrayList<Double> remaining = new ArrayList<Double>(numbers);
remaining.remove(num);
if (target == num)
{
done = true;
}
else
{
done = solve(target + num, remaining);
if (done)
{
print += ((int) target + (int) num) + " " + "-" + " " + (int) num + " "
+ "="
+ " "
+ ((int) target + "\n");
}
else
{
done = solve(target - num, remaining);
if (done)
{
print += ((int) target - (int) num) + " " + "+" + " " + (int) num + " "
+ "=" + " "
+ ((int) target + "\n");
}
else
{
done = solve(target * num, remaining);
if (done)
{
print += ((int) target * (int) num) + " " + "/" + " " + (int) num
+ " " + "=" + " "
+ ((int) target + "\n");
}
else
{
done = solve(target / num, remaining);
if (done)
{
print += ((int) target / (int) num) + " " + "*" + " "
+ (int) num
+ " " + "="
+ " " + ((int) target + "\n");
}
}
}
}
}
}
}
System.out.print(print);
return done;
}
}
For instance:
void recursiveF(...) {
if ... {
recursiveF(...);
println();
}
...
}
The result is a string but you don't want the last character, so remove it:
print = print.substring(0, print.length()-1);
Use trim() method. It will remove white spaces, newline etc from beginning and end of string.
System.out.print(print.trim());
Short Print the new line character before.
The first thing the recursive function should do is print the new line character.
This way you shift the odd case from the last function call, to the first call, which should not prepend a new line character.
You could add a parameter String prepend = "" to the signature of the recursive method, it's empty on the first call, all further calls have it set to String prepend = "\n".
Then you can just print prepend without bothering with its content.

Categories

Resources