Can someone help me make this code more efficient? [closed] - java

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I'm creating a skill tree calculator for a game. I wrote a method that checks whether or not it can subtract a point from the skill and then proceeds to do so. Everything is working as it should, however it's very slow when this method is executed in rapid succession (i.e. when 5 points are subtract at the same time).
Can anyone help me with this and more important explain why certain things are faster and what to avoid?
Here is the method:
public void cmdSubtractPoint(int index, SkillTree tree) {
boolean subtract = false;
if (this.blueTree.get(index).getInvestedPoints() != 0) {
//Only subtract a point if the skill isn't empty
if (index == 0 || index == 1) {
if ((((this.blueTree.get(0).getInvestedPoints() + this.blueTree.get(1).getInvestedPoints()) - 1) < 5)
&& ((this.blueTree.get(2).getInvestedPoints() + this.blueTree.get(3).getInvestedPoints() +
this.blueTree.get(4).getInvestedPoints() + this.blueTree.get(5).getInvestedPoints() + this.blueTree.get(6).getInvestedPoints()) != 0)) {
this.showToast();
} else if ((((this.blueTree.get(0).getInvestedPoints() + this.blueTree.get(1).getInvestedPoints()) + this.blueTree.get(2).getInvestedPoints() + this.blueTree.get(3).getInvestedPoints() - 1) < 10)
&& ((this.blueTree.get(4).getInvestedPoints() + this.blueTree.get(5).getInvestedPoints() + this.blueTree.get(6).getInvestedPoints()) != 0)) {
this.showToast();
} else if ((((this.blueTree.get(0).getInvestedPoints() + this.blueTree.get(1).getInvestedPoints()) + this.blueTree.get(2).getInvestedPoints() + this.blueTree.get(3).getInvestedPoints() + this.blueTree.get(4).getInvestedPoints() + this.blueTree.get(5).getInvestedPoints() - 1) < 15)
&& ((this.blueTree.get(6).getInvestedPoints()) != 0)) {
this.showToast();
} else {
subtract = true;
}
} else if (index == 2 || index == 3) {
if ((((this.blueTree.get(0).getInvestedPoints() + this.blueTree.get(1).getInvestedPoints()) + this.blueTree.get(2).getInvestedPoints() + this.blueTree.get(3).getInvestedPoints() - 1) < 10)
&& ((this.blueTree.get(4).getInvestedPoints() + this.blueTree.get(5).getInvestedPoints() + this.blueTree.get(6).getInvestedPoints()) != 0)) {
this.showToast();
} else if ((((this.blueTree.get(0).getInvestedPoints() + this.blueTree.get(1).getInvestedPoints()) + this.blueTree.get(2).getInvestedPoints() + this.blueTree.get(3).getInvestedPoints() + this.blueTree.get(4).getInvestedPoints() + this.blueTree.get(5).getInvestedPoints() - 1) < 15)
&& ((this.blueTree.get(6).getInvestedPoints()) != 0)) {
this.showToast();
} else {
subtract = true;
}
} else if (index == 4 || index == 5) {
if ((((this.blueTree.get(0).getInvestedPoints() + this.blueTree.get(1).getInvestedPoints()) + this.blueTree.get(2).getInvestedPoints() + this.blueTree.get(3).getInvestedPoints() + this.blueTree.get(4).getInvestedPoints() + this.blueTree.get(5).getInvestedPoints() - 1) < 15)
&& ((this.blueTree.get(6).getInvestedPoints()) != 0)) {
this.showToast();
} else {
subtract = true;
}
} else if (index == 6) {
subtract = true;
}
if (subtract) {
this.pointsInBlueTree -= 1;
this.blueTree.get(index).subtractPoint();
}
}
}

If reduce value calculation to one time and use switch, you will obtain code similar this:
public void cmdSubtractPoint(int index, SkillTree tree) {
boolean subtract = false;
if (this.blueTree.get(index).getInvestedPoints() != 0) {
// Only subtract a point if the skill isn't empty
int temp01 = this.blueTree.get(0).getInvestedPoints() + tree.blueTree.get(1).getInvestedPoints();
int temp23 = this.blueTree.get(2).getInvestedPoints() + tree.blueTree.get(3).getInvestedPoints();
int temp45 = this.blueTree.get(4).getInvestedPoints() + tree.blueTree.get(5).getInvestedPoints();
int temp6 = this.blueTree.get(6).getInvestedPoints();
switch (index) {
case 0:
case 1:
if (((temp01 ) < 6) && ((temp23 + temp45 + temp6) != 0)) {
this.showToast();
} else if (((temp01 + temp23) < 11) && ((temp45 + temp6) != 0)) {
this.showToast();
} else if (((temp01 + temp23 + temp45) < 16) && (temp6 != 0)) {
this.showToast();
} else {
subtract = true;
}
break;
case 2:
case 3:
if (((temp01 + temp23) < 11) && ((temp45 + temp6) != 0)) {
this.showToast();
} else if (((temp01 + temp23 + temp45) < 16) && (temp6 != 0)) {
this.showToast();
} else {
subtract = true;
}
break;
case 4:
case 5:
if (((temp01 + temp23 + temp45) < 16) && (temp6 != 0)) {
this.showToast();
} else {
subtract = true;
}
break;
case 6:
subtract = true;
break;
}
if (subtract) {
this.pointsInBlueTree -= 1;
this.blueTree.get(index).subtractPoint();
}
}
}

Related

Optimizing If- else if- else statements in Java

In doing a lotto checker program, where one of the constraints is to not use loops, or data structures like arrays, lists etc I've written the following piece of code to check if the 3 entries given by the user (draw1, draw2, draw3) are equal to any of the 7 random numbers generated by the program (random1, random2, random3, ...).
if (random1==draw1 || random2==draw1 || random3==draw1 || random4==draw1|| random5==draw1
|| random6==draw1 || random7==draw1)
{
if(random1==draw2 || random2==draw2 || random3==draw2 || random4==draw2|| random5==draw2
|| random6==draw2 || random7==draw2)
{
if(random1==draw3 || random2==draw3 || random3==draw3 || random4==draw3|| random5==draw3
|| random6==draw3 || random7==draw3)
{
str = str +'\n' + "The following 3 matches were found:" +'\n'+ draw1 + " " + draw2
+ " " + draw3 ;
}else
{
str = str + '\n' + "The following 2 matches were found:" + '\n' + draw1 + " " + draw2;
}
}else if (random1==draw3 || random2==draw3 || random3==draw3 || random4==draw3|| random5==draw3
|| random6==draw3 || random7==draw3)
{
str = str + '\n' + "The following 2 matches were found:" + '\n' + draw1 + " " + draw3 ;
}
else
{
str = str + '\n' + "The following 1 matches were found:" + '\n' + draw1;
}
}else if (random1==draw2 || random2==draw2 || random3==draw2 || random4==draw2|| random5==draw2
|| random6==draw2 || random7==draw2)
{
if(random1==draw3 || random2==draw3 || random3==draw3 || random4==draw3|| random5==draw3
|| random6==draw3 || random7==draw3)
{
str = str + '\n' + "The following 2 matches were found:" + '\n' + draw2 + " " + draw3;
}
else
{
str = str + '\n' + "The following 1 matches were found:" + '\n' + draw2;
}
}
else if (random1==draw3 || random2==draw3 || random3==draw3 || random4==draw3|| random5==draw3
|| random6==draw3 || random7==draw3)
{
str = str + '\n' + "The following 1 matches were found:" + '\n' + draw3;
}
else
{
str = str + '\n' + "The following 0 matches were found:" ;
}
How can I go about optimizing this and most importantly will the optimization only increase readability or will it contribute to the efficiency of the program?
Use sets, this will improve readabilty.
Set<Integer> luckyNumbers = new HashSet<>();
//Add your numbers to the set
//Integer i = ...
//luckyNumbers.add(i);
Set<Integer> drawNumbers = new HashSet<>();
//Integer i = ...
//drawNumbers.add(i);
Set<Integer> matchNumbers = new HashSet<>(luckyNumbers);
matchNumbers.retainAll(drawNumbers);
//In matchNumbers will be the intersection of the previous sets.
//There you can get the size of the intersection set or its content to show the
//matches
If you want to use a loop for this part you can do something like this:
System.out.println("Number of matches: " + matchNumbers.size());
for(Integer matchNumber : matchNumbers){
System.out.println("Match number: " + matchNumber);
}
Try this.
static boolean equalsAny(int base, int... comparisons) {
for (int c : comparisons)
if (base == c)
return true;
return false;
}
and you can rewrite
if (random1 == draw1 || random2 == draw1 || random3 == draw1 || random4 == draw1 || random5 == draw1
|| random6 == draw1 || random7 == draw1) {
to
if (equalsAny(draw1, random1, random2, random3, random4, random5, random6, random7)) {

how do you convert a number in a text form to a number?

What is the code wherein if you input any number in text form line for example "twenty seven" the output is 27?
but with this code it will take time to make it reach like in millions that is why I want to know what can be done to make things efficient
import java.util.Scanner;
public class conversion {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter A Number In Text Form: ");
String inp = input.nextLine();
if (inp.equals("zero")) {
System.out.println("0");
} else if (inp.equals("one")) {
System.out.println("1");
} else if (inp.equals("two")) {
System.out.println("2");
} else if (inp.equals("three")) {
System.out.println("3");
} else if (inp.equals("four")) {
System.out.println("4");
} else if (inp.equals("five")) {
System.out.println("5");
} else if (inp.equals("six")) {
System.out.println("6");
} else if (inp.equals("seven")) {
System.out.println("7");
} else if (inp.equals("eight")) {
System.out.println("8");
} else if (inp.equals("nine")) {
System.out.println("9");
}
}
}
create a dictionary map with all possible but minimal combinations :
e.g var dics= { twenty :20 , two: 2}
Now you can split your input string by space. and then try to build a logic to utilize these values.
this will be complex to implement for sure but yes , it's possible.
You can split the string to an array with split function.
and loop it
String[] inps = inp.split(" ");
int remaining = inps.length;
String outstr = "";
for (String numstr : inps)
{
remaining--;
int digit = 0;
switch (numstr.toLowerCase()) // in the JDK7, You can use Strings in switch
{
case "twenty": outstr += '2'; digit=10; break;
case "thirty": outstr += '3'; digit=10; break;
// ...
}
if (digit == 10 && remaining == 0)
{
// tenth digit, but no remaining
outstr += '0';
}
}
System.out.println(outstr);
public static final String[] tens = {
"", // 0
"", // 1
"Twenty", // 2
"Thirty", // 3
"Forty", // 4
"Fifty", // 5
"Sixty", // 6
"Seventy", // 7
"Eighty", // 8
"Ninety" // 9
};
public static String convert(final int n) {
if (n < 0) {
return "Minus " + convert(-n);
}
if (n < 20) {
return units[n];
}
if (n < 100) {
return tens[n / 10] + ((n % 10 != 0) ? " " : "") + units[n % 10];
}
if (n < 1000) {
return units[n / 100] + " Hundred" + ((n % 100 != 0) ? " " : "") + convert(n % 100);
}
if (n < 100000) {
return convert(n / 1000) + " Thousand" + ((n % 10000 != 0) ? " " : "") + convert(n % 1000);
}
if (n < 10000000) {
return convert(n / 100000) + " Lakh" + ((n % 100000 != 0) ? " " : "") + convert(n % 100000);
}
return convert(n / 10000000) + " Crore" + ((n % 10000000 != 0) ? " " : "") + convert(n % 10000000);
}
public static void main(final String[] args) {
int n;
Scanner s=new Scanner(System.in);
System.out.println("Enter a number to convert into word format");
n =s.nextInt();
System.out.println(NumberFormat.getInstance().format(n) + "='" + convert(n) + "'");
}

How to get time difference between two ZonedDateTimes and pretty print it like "4 hours, 1 minute, 40 seconds ago"?

This is how I call getTimeBetween function:
getTimeBetween(ZonedDateTime.now().minusHours(4).minusMinutes(1).minusSeconds(40), ZonedDateTime.now());
And I expect this output:
4 hours, 1 minute, 40 seconds ago
This is my getTimeBetween function:
private String getTimeBetween(ZonedDateTime zonedDateTime1, ZonedDateTime zonedDateTime2) {
Duration timeDifference = Duration.between(zonedDateTime1, zonedDateTime2);
if (timeDifference.getSeconds() == 0) return "now";
String timeDifferenceAsPrettyString = "";
Boolean putComma = false;
if (timeDifference.toDays() > 0) {
if (timeDifference.toDays() == 1) timeDifferenceAsPrettyString += timeDifference.toDays() + " day";
else timeDifferenceAsPrettyString += timeDifference.toDays() + " days";
putComma = true;
}
if (timeDifference.toHours() > 0) {
if (putComma) timeDifferenceAsPrettyString += ", ";
if (timeDifference.toHours() == 1) timeDifferenceAsPrettyString += timeDifference.toHours() + " hour";
else timeDifferenceAsPrettyString += timeDifference.toHours() % 24 + " hours";
putComma = true;
}
if (timeDifference.toMinutes() > 0) {
if (putComma) timeDifferenceAsPrettyString += ", ";
if (timeDifference.toMinutes() == 1) timeDifferenceAsPrettyString += timeDifference.toMinutes() + " minute";
else timeDifferenceAsPrettyString += timeDifference.toMinutes() % 60 + " minutes";
putComma = true;
}
if (timeDifference.getSeconds() > 0) {
if (putComma) timeDifferenceAsPrettyString += ", ";
if (timeDifference.getSeconds() == 1) timeDifferenceAsPrettyString += timeDifference.getSeconds() + " second";
else timeDifferenceAsPrettyString += timeDifference.getSeconds() % 60 + " seconds";
}
timeDifferenceAsPrettyString += " ago";
return timeDifferenceAsPrettyString;
}
This function works as expected but is it really necessary to do it like this? Perhaps there is a better way to achieve this?
I'm using Java 8.
How about this?
static String getTimeBetween(ZonedDateTime from, ZonedDateTime to) {
StringBuilder builder = new StringBuilder();
long epochA = from.toEpochSecond(), epochB = to.toEpochSecond();
long secs = Math.abs(epochB - epochA);
if (secs == 0) return "now";
Map<String, Integer> units = new LinkedHashMap<>();
units.put("day", 86400);
units.put("hour", 3600);
units.put("minute", 60);
units.put("second", 1);
boolean separator = false;
for (Map.Entry<String, Integer> unit : units.entrySet()) {
if (secs >= unit.getValue()) {
long count = secs / unit.getValue();
if (separator) builder.append(", ");
builder.append(count).append(' ').append(unit.getKey());
if (count != 1) builder.append('s');
secs %= unit.getValue();
separator = true;
}
}
return builder.append(epochA > epochB ? " ago" : " in the future").toString();
}
You could probably store the LinkedHashMap instead of instantiating it every method call, but this should work.

Beginner Help: What is wrong with this method?

I'm creating a Tic Tac Toe game and this is the way I am checking for the win. I get this list of errors in this section of code:
/tmp/java_hoEysf/TicTacToe.java:195: error: not a statement Public
void Checkforwin(); ^ /tmp/java_hoEysf/TicTacToe.java:195: error:
';' expected Public void Checkforwin();
^ /tmp/java_hoEysf/TicTacToe.java:195: error: illegal start of expression Public void Checkforwin();
Can anyone tell me what I'm doing wrong? (The code is not complete and I'm just wondering why the method won't work.)
Code:
public void checkForWin() {
if (board [0][0] + board[0][1] + board[0][2] == 15) {
btnA3.setText("Ax");
win = 1;
}
if (board [0][0] + board[0][1] + board[0][2] == 30) {
btnA3.setText("Ao");
win = 2;
}
if (board[1][0] + board[1][1] + board[1][2] == 15) {
btnA3.setText("Ax");
win = 1;
}
if (board[1][0] + board[1][1] + board[1][2] == 30) {
btnA3.setText("Ao");
win = 2;
}
if (board[2][0] + board[2][1] + board[2][2] == 15) {
btnA3.setText("Ax");
win = 1;
}
if (board[2][0] + board[2][1] + board[2][2] == 30) {
btnA3.setText("Ao");
win = 2;
}
if (board[0][0] + board[1][0] + board[2][0] == 15) {
btnA3.setText("Ax");
win = 1;
}
if (board[0][0] + board[1][0] + board[2][0] == 30) {
btnA3.setText("Ao");
win = 2;
}
}
In Java the right keyword is public not Public, indeed it is case sensitive.
You can find the list of all the existing keywords in Java and their meaning here.

How to detect whitespace of operator

I have some problem about my code.
I want to detect whitespace of operator like " + ", " +", "+ " or "+".
I want my output is
Whitespace of an operator is "A"
How can I modify my code?
My code is here.
Scanner input = new Scanner (new File(PATH to file));
int plus1;
int plus2;
int plus3;
int plus4;
String sPlus = "";
while (in.hasNext()) {
String line = in.nextLine();
in.hasNextLine();
LOC++;
if (line.length() > 0) {
plus1 = -1;
plus2 = -1;
plus3 = -1;
plus4 = -1;
while (true) {
plus1 = line.indexOf(" + ", plus1 + 1);
plus2 = line.indexOf(" +", plus2 + 1);
plus3 = line.indexOf("+ ", plus3 + 1);
plus4 = line.indexOf("+", plus4 + 1);
if (plus1 > 0) {
sPlus = "A";
}
if (plus2 > 0) {
sPlus = "B";
}
if (plus3 > 0) {
sPlus = "C";
}
if(plus4 > 0){
sPlus = "D";
}
if ((plus1 < 0) || (plus2 < 0) || (plus3 < 0) || (plus4 < 0)) break;
}
}
}
There are two problems with your logic:
You are using trim() in line.indexOf(" +".trim(), plus2+1), which returns the index of "+" NOT " +"
Any one occurrence of " + " will be counted 4 times, because line.indexOf(" +") will also count occurrences of " + "
For 2. it would be much easier to use line.indexOf('+'), and then check before and after the index to see how many whitespaces there are:
int plus = line.indexOf('+');
if(plus == -1) break;
if(line.charAt(plus-1) == ' ') {
if(line.charAt(plus+1) == ' ') //A;
else //B;
}
else if(line.charAt(plus+1) == ' ') {
//C
}
else {
//D
}
Proper else-if could be help.
if (line.indexOf(" + ") != -1) sPlus = "A";
else if (line.indexOf(" +") != -1) sPlus = "B";
else if (line.indexOf("+ ") != -1) sPlus = "C";
else if (line.indexOf("+") != -1) sPlus = "D";
else break;

Categories