Optimizing If- else if- else statements in Java - 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)) {

Related

Min, Max and equals for three numbers in Java

I am currently up with Java and there is a question which I am not getting a correct approach to. It says to find out the minimum and maximum of two numbers, as well as the numbers which are equal, in if statements (nested ifs are allowed) and It's getting very complex and hard-to-understand. Can you suggest a better way to do it ?
Here's my code :
long num1 = 1 ;
long num2 = 1 ;
long num3 = 1 ;
boolean error = false ;
Scanner sc = new Scanner(System.in) ;
do {
if(error)
{
System.out.println("Sorry, error. Try again") ;
}
error = false ;
System.out.print("Enter the first number : ") ;
num1 = sc.nextLong() ;
System.out.print("Enter the second number : ") ;
num2 = sc.nextLong() ;
System.out.print("Enter the third number : ") ;
num3 = sc.nextLong() ;
if(num1<=0 || num2<=0) error = true ;
// number entered will iterate if error...
while(error == true) ;
// main conditions
if(num1>num2)
{
if(num1>num3)
{
System.out.println(num1 + " is the greatest number") ;
if(num2<num3)
{
System.out.println(num2 + " is the smallest") ;
} else if(num2==num3) {
System.out.println(num2 + " and " + num3 + " are equal") ;
}
}
} else if(num2>num3) {
if(num1!=num2)
{
System.out.println(num2 + " is the greatest number") ;
} else {
System.out.println(num2 + " and " + num1 + " are equal") ;
}
if(num1<num3)
{
System.out.println(num1 + " is the smallest number") ;
} else if(num1==num3) {
System.out.println(num1 + " and " + num3 + " are equal") ;
}
} else if(num3>num2){
if(num3!=num1)
{
System.out.println(num3 + " is the greatest") ;
} else {
System.out.println(num3 + " and " + num1 + " are equal") ;
}
}
}
I know this program does not cover all the possibilities, and sure enough, when i run it, it does not display all the correct results. Can anybody send me an organised program (with comments) please? It will be highly appreciated.
It is very simple, you can use the max and min functions of the Math module. It goes like this
long a, b, c
a = Math.max(num1, Math.max(num2, num3))
//a will be the maximum number
b = Math.min(num1,Math.min(num2, num3))
//b will be the minimum number
//c is the middle number
if(num1 < a & num1 > b)
c = num1
else if(num2 < a & num2 > b)
c = num2
else
c = num3
The way to this question is really easy (can't see why nobody saw it before) - just use the AND operator.
So for finding out the GREATEST number among the three :
if(num1>num2 && num1>num3)
{
System.out.println(num1 + " is the greatest") ;
} else if(num2>num3 && num2>num1) {
System.out.println(num2 + " is the greatest") ;
} else if(num3>num2 && num3>num1) {
System.out.println(num3 + " is the greatest") ;
}
For finding out the SMALLEST number :
if(num1<num2 && num1<num3) {
System.out.println(num1 + " is the smallest") ;
} else if(num2<num3 && num2<num1) {
System.out.println(num2 + " is the smallest") ;
} else if(num3<num2 && num3<num1) {
System.out.println(num3 + " is the smallest") ;
}
for finding out the EQUAL numbers :
if(num1==num2 && num2==num3) {
System.out.println("All the numbers are equal") ;
} else if(num2==num3) {
System.out.println(num2 + " is equal to " + num3) ;
} else if(num1==num3) {
System.out.println(num1 + " is equal to " + num3) ;
} else if(num1==num2) {
System.out.println(num1 + " is equal to " + num2) ;
}
Combining all of them :
public static void main()
{
long num1 = 1 ;
long num2 = 1 ;
long num3 = 1 ;
boolean error = false ;
Scanner sc = new Scanner(System.in) ;
do {
if(error)
{
System.out.println("Sorry, error. Try again") ;
}
error = false ;
System.out.print("Enter the first number : ") ;
num1 = sc.nextLong() ;
System.out.print("Enter the second number : ") ;
num2 = sc.nextLong() ;
System.out.print("Enter the third number : ") ;
num3 = sc.nextLong() ;
if(num1<=0 || num2<=0) error = true ;
// number entered will iterate if error...
} while(error == true) ;
if(num1>num2 && num1>num3)
{
System.out.println(num1 + " is the greatest") ;
} else if(num2>num3 && num2>num1)
{
System.out.println(num2 + " is the greatest") ;
} else if(num3>num2 && num3>num1)
{
System.out.println(num3 + " is the greatest") ;
}
if(num1<num2 && num1<num3)
{
System.out.println(num1 + " is the smallest") ;
} else if(num2<num3 && num2<num1)
{
System.out.println(num2 + " is the smallest") ;
} else if(num3<num2 && num3<num1)
{
System.out.println(num3 + " is the smallest") ;
}
System.out.println() ; // for clarity
if(num1==num2 && num2==num3)
{
System.out.println("All the numbers are equal") ;
} else if(num2==num3)
{
System.out.println(num2 + " is equal to " + num3) ;
} else if(num1==num3)
{
System.out.println(num1 + " is equal to " + num3) ;
} else if(num1==num2)
{
System.out.println(num1 + " is equal to " + num2) ;
}
}
}
[NOTE: the lines are not indented properly-so please overlook that.]

Tic tac toe game predict a tie(draw)

I'm making a tic tac toe game for my homework and the teacher told me to print a tie when only a tie can come out. (under the assumption that the players are not smart) For example,
x o x
- - -
o x o
can only result in a tie so when this happens we are supposed to end the game with "this is a tie"
I have finished coding the tic tac toe with a char[][] array but I have no idea how to predict a draw.
public class Ttt22 {
private static int spacesLe
private static char[][] board;
public static void main (String[] args) {
// the first move belongs to X.
System.out.println("Welcome to Tic Tac Toe");
board = new char[3][3];
initializeBoard();
firstDraw();
char mark = 'X';
while (true) {
int square = getLegalMove(mark);
move(square, mark);
draw();
if (is3InRow(mark)) {
System.out.println(mark + " wins!");
break;
}
if (isBoardFull()) {
System.out.println("Tie game!");
break;
}
if (mark == 'X') {
mark = 'O';
}
else {
mark = 'X';
}
}
}
public static int getLegalMove (char mark) {
java.util.Scanner console = new java.util.Scanner(System.in);
while (true) {
System.out.println(mark + "'s next move: ");
int square = console.nextInt();
if ((square >= 1) &&
(square <= 9) &&
(isSquareEmpty(square))) {
return square;
}
System.out.println("\nIllegal move, try again\n");
}
}
public static void initializeBoard () {
spacesLeft = 9;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
board[i][j] = ' ';
}
}
}
public static void firstDraw () {
System.out.println();
System.out.println(" | | ");
System.out.println(" " + 1 + " | " + 2 + " | " + 3);
System.out.println(" | | ");
System.out.println("---+---+---");
System.out.println(" | | ");
System.out.println(" " + 4 + " | " + 5 + " | " + 6);
System.out.println(" | | ");
System.out.println("---+---+---");
System.out.println(" | | ");
System.out.println(" " + 7 + " | " + 8 + " | " + 9);
System.out.println(" | | ");
System.out.println();
}
public static void draw () {
System.out.println();
System.out.println(" | | ");
System.out.println(" " + board[0][0] + " | "
+ board[0][1] + " | " + board[0][2]);
System.out.println(" | | ");
System.out.println("---+---+---");
System.out.println(" | | ");
System.out.println(" " + board[1][0] + " | "
+ board[1][1] + " | " + board[1][2]);
System.out.println(" | | ");
System.out.println("---+---+---");
System.out.println(" | | ");
System.out.println(" " + board[2][0] + " | "
+ board[2][1] + " | " + board[2][2]);
System.out.println(" | | ");
System.out.println();
}
public static void move (int square, char mark) {
if (isSquareEmpty(square)) {
spacesLeft = spacesLeft - 1;
}
int row = (square - 1) / 3;
int column = (square - 1) % 3;
board[row][column] = mark;
}
public static boolean isSquareEmpty (int square) {
int row = (square - 1) / 3;
int column = (square - 1) % 3;
return (board[row][column] == ' ');
}
public static boolean is3InRow (char mark) {
return
(board[0][0] == mark && board[0][1] == mark && board[0][2] == mark) ||
(board[1][0] == mark && board[1][1] == mark && board[1][2] == mark) ||
(board[2][0] == mark && board[2][1] == mark && board[2][2] == mark) ||
(board[0][0] == mark && board[1][0] == mark && board[2][0] == mark) ||
(board[0][1] == mark && board[1][1] == mark && board[2][1] == mark) ||
(board[0][2] == mark && board[1][2] == mark && board[2][2] == mark) ||
(board[0][0] == mark && board[1][1] == mark && board[2][2] == mark) ||
(board[0][2] == mark && board[1][1] == mark && board[2][0] == mark);
}
public static boolean isBoardFull () {
return spacesLeft == 0;
}
}
the expected result is when the game is
x o x
- - -
o x o
It prints "Tie game!" and the game ends
Hmm, simply, after every move of the "players", launch an automatic process that will compute all outcomes of the game starting from that particular position. If all of those end in a draw, then you can safely declare that the final outcome is a draw. Of course, this is the first, not at all optimized solution, that comes to my mind immediately. If you are interested, you can probably work on some optimizations based on that.
There are algorithms for this kind of task, I suggest you read about Minimax

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;

Better Algorithm? Better Array?

This is my code:
/* Name: Steven Royster
* Date: Jan. 15, 2015
* Rock, Paper, Scissors Program
* This program simulates a game of rock, paper, scissors with the user until someone has one a total of five times.
*/
import java.util.Random;
import java.util.Scanner;
public class RPS {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Let's play rock, paper, scissors! First to five wins!");
String[] choice = { "zero" , "rock" , "paper" , "scissors" };
Random rander = new Random();
Scanner input = new Scanner(System.in);
int userScore = 0, compScore = 0,
userChoice, compChoice;
while (compScore < 5 && userScore < 5)
{
compChoice = rander.nextInt(3) + 1;
System.out.println("\nEnter: 1 for ROCK | 2 for PAPER | 3 for SCISSORS.");
userChoice = input.nextInt();
if (compChoice == userChoice) // tie
{
System.out.println("I chose " + choice[compChoice] + " too, so we tied!");
}
else if ( ( compChoice == 1 && userChoice == 3 ) //computer wins
|| ( compChoice == 2 && userChoice == 1 )
|| ( compChoice == 3 && userChoice == 2) )
{
System.out.println("I win! I chose " + choice[compChoice] + ". " +
choice[compChoice] + " beats " + choice[userChoice] + "." );
compScore += 1;
}
else //human wins
{
System.out.println("You win! I chose " + choice[compChoice] + ". " +
choice[userChoice] + " beats " + choice[compChoice] + ".");
userScore += 1;
}
}//end while
if (userScore == 5)
{
System.out.println("\nCongrats! You're the winner! You got "
+ userScore + " points. I only got " + compScore + " points." );
}
}//end main
}//end class
Is there a better algorithm I can implement rather than using the three separate conditions within my else-if statement? Also, instead of having the 'zero' string in my array, how could I check through my array using only numbers 1, 2, and 3?
Just use
String[] choice = { "rock" , "paper" , "scissors" };
Then instead of choice[userChoice] you can do choice[userChoice - 1].
You don't need to write
if ( ( compChoice == 1 && userChoice == 3 )
|| ( compChoice == 2 && userChoice == 1 )
|| ( compChoice == 3 && userChoice == 2) )
because it is the same as
if (compChoice == 1 + (userChoice % 3))

Why does this condition always return false?

Could anyone please tell me what is wrong with the following code. It doesn't show any result.
The integer a,b,c are the side of an right angle triangle.(was solving Project Euler problem 39)
If I use || in place of && , it shows the desired result based on the || condition. But doesn't work with the && condition
public static void main(String[] args) {
int a,b,c;
for (a=1;a<120;a++){
for(b=120;b>0;b--){
c= 120-(a+b);
if (((c) > (a+b)) && ((c*c)==(a*a)+(b*b))){
System.out.println(a + " , " + b +" , " + c);
System.out.println("**************");
}
}
}
}
Quite simply, it's because this expression:
((c) > (a+b))
...never returns true in your example for any valid right angled triangles, and since the && condition requires both operands to evaluate to true, the if statement isn't executed.
You can see this quite clearly if you put in the following lines:
System.out.println("C: " + c);
System.out.println("A+B: " + a+b);
second part of && condition will always be false if first it true. if c > (a+b) then c*c > (a+b)*(a+b) => c^2 > a^2 + b^2 + 2ab then c^2 != a^2 + b^2
Isn't a+b always 121? making c always -1, making c > a+b an illogical comparison? Just what are you attempting to do here?
Anyway, add some System.outs after each { so you know what is happening.
Also add System.out.println( c + " " + a + " " + b + " " + (a+b) + " " + (c*c) + " " + ((a*a)+(b*b))); to see all the parameters in your comparison to make sure you get what you expect before the if itself.
Mathematically both this conditions will never be true that is why && results into false and || works as one of the condition is true in a situation.
(c > (a+b)) && (c*c==(a*a)+(b*b))
If a number is greater than sum of two number then square of the number will be also greater then sum of square of two numbers.
try this
int a,b,c;
for (a=1;a<120;a++) {
for(b=120;b>0;b--){
c= 120-(a+b);
System.out.println(c+">"+(a+b)+" && "+(c*c)+" == "+((a*a)+(b*b)));
if (((c) > (a+b)) && ((c*c)==(a*a)+(b*b))){
System.out.println(a + " , " + b +" , " + c);
System.out.println("**************");
}
}
}
}
and check yourself
i.e.
-66>186 && 4356 == 17330
-65>185 && 4225 == 17137
-64>184 && 4096 == 16946
-63>183 && 3969 == 16757
-62>182 && 3844 == 16570
-61>181 && 3721 == 16385
-60>180 && 3600 == 16202
-59>179 && 3481 == 16021
-58>178 && 3364 == 15842
...

Categories