How can I make this more efficient? - java

My program gives a String answer based on comparisons of Integer input. Would there be a more efficient way of doing this instead of prompting the user 3 separate times and calling numberVerify three separate times? How would I do this? Very new to Java.
public static void main(String[] args) {
// TODO code application logic here
// declare variables
int number=0;
System.out.println("Enter the first integer: ");
int number1 = numberVerify(number);
System.out.println("Enter the second integer: ");
int number2 = numberVerify(number);
System.out.println("Enter the third integer: ");
int number3 = numberVerify(number);
String compare = comparison(number1, number2, number3);
printer(compare);
}
public static int numberVerify(int number){
Scanner in = new Scanner(System.in);
if(in.hasNextInt()){
number = in.nextInt();
}
else{
System.out.println("Error! Input must be an integer!");
System.out.println("");
return numberVerify(number);
}
return number;
}
public static String comparison(int number1, int number2, int number3){
String answer;
if(number1 == number2 && number1 == number3)
{
answer = "all the same";
}
else if(number1 != number2 && number1 != number3)
{
answer = "all different";
}
else
{
answer = "neither";
}
return answer;
}
public static void printer(String answer){
System.out.println(answer);
}

Efficiency is irrelevant here.
The user is going to take SECONDS to enter the number. The OS could take MILLISECONDS to do the keyboard event processing, screen redrawing etc. Your Java application is going to take MICROSECONDS or less to do the decision making. Any effort you expend to reduce the microsecond component is wasted effort.
If there are issues to be addressed here (and I'm not saying there are) they would be:
making the user interface easy to use.
writing the code so that it is easy to read and easy to maintain.
writing the code to be "elegant" ... which is not necessarily the same as the previous.
UPDATE - Apparently you are actually interested in simplifying and/or reducing the size of the code.
Firstly, that's NOT what most people mean by efficiency. (Indeed, I would argue that spending time on improving code that is good enough is inefficient use of your time.)
Secondly, simplicity and code size are not the same things. Most people (programmers) would say that simple code is code that is easy to understand ... for the average programmer. Often, a more concise solution to a problem will actually be difficult to understand. (Take #rby's code for example. If you needed to be sure it was correct without testing it, you would need to read it very carefully.)
Finally, professional software engineers follow the general principle that the code needs to be "good enough for purpose"1 ... but no better. Perfect is the enemy of good. Spending your time making a program better than it needs to be is wasting your time, and liable to cost you / your client / your employer money.
1 - The purpose may include performance criteria, readability / maintainability, generality / resuability, and various specific correctness criteria. But that is not necessarily the case. Often, code is written for a context where many of those criteria are irrelevant or even counter-productive. But I digress ....

Use an int array and a for loop instead say :
int [] values = new int[3];
for(int i =0; i<3; i++){
values[i] = in.nextInt();
}
Then modify your compare method to use the array;
For brownie points look up Sets and figure how you can eliminate most of your comparison method with them.

You can use the following single line to replace your entire if blocks in method comparison and return answer as you do:
answer = ( (n1 == n2) ?
( (n2 == n3) ? "all equal" : "neither") :
( n1 == n3) ? "neither" : ( ( n2 == n3 ) ? "neither" : "all different" ) );
return answer;

You can use arrays and little other modifications to make it efficient.
Here is the code.
import java.util.Scanner;
public class efficient {
private static String comparison(int[] numberArray) {
String answer;
if(numberArray[0] == numberArray[1] && numberArray[1] == numberArray[2]){
answer = "all the same";
}else if(numberArray[0] != numberArray[1] && numberArray[1] != numberArray[2]){
answer = "all different";
}else{
answer = "neither";
} return answer;
}
public static void main(String[] args) {
int[] numberArray = new int[3];
Scanner scan = new Scanner(System.in);
System.out.println("Enter the numbers");
for(int i=0;i<=numberArray.length-1;i++){
if(scan.hasNextInt()){
numberArray[i]=scan.nextInt();
}else{
System.out.println("Error! Input must be an integer!");
}
}
String compare = comparison(numberArray);
System.out.println(compare);
}
}

I don't know about more efficient or readable, it seems that way already. But I can make it shorter.
public static void main(String[] args) {
// TODO code application logic here
// declare variables
Scanner in = new Scanner(System.in);
int[] numbers = new int[3];
String[] labels = {"first","second","third"};
for(int i=0; i<3; i++)
{
System.out.print("Enter the " + labels[i] + " integer: ");
numbers[i] = in.nextInt();
}
System.out.println(comparison(numbers[0],numbers[1],numbers[2]));
}
public static String comparison(int number1, int number2, int number3){
String answer;
if(number1 == number2 && number1 == number3)
{
answer = "all the same";
}
else if(number1 != number2 && number1 != number3 && number2 != number3)
{
answer = "all different";
}
else
{
answer = "neither";
}
return answer;
}

Related

how can i check if the number is perfect square by not using math.sqrt

i want to make a program which related to this question:
An integer that can be expressed as the square of another integer is called a perfect square, such as 4,9,16,25, etc. Write a progran that checks if a number is a perfect square.
I did built something goes like:
import java.util.Scanner;
class Q3{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int num = 0;
int a = 0;
System.out.println("Type a number to check if it has square");
num = sc.nextInt();
for(a = 1;a<num;a++){ }
if (a*a == num){
System.out.println("Ok");
break;
}
else if (a*a != num){
System.out.println("Not ok");
}
}
}
So it doesn’t give what i want when i run it. What should i change or add ?
I think your for loop interpretation might be wrong, I made up something that might just work. Give this code a try.. You can make the method return a boolean too if you want.
static void perfectSquare(int number) {
for (int i = 1; i < i * number; ++i) {
// 'i' is the divisor, making sure
// it is equal to the quotient
if ((number % i == 0) && (number / i == i)) {
System.out.println(i);
}
}
If you want to brute force every number then you are on the right track but you should only print "Not ok" if all numbers in the loop have failed otherwise you may have a perfect square but "Ok" will be hidden within many "Not ok" lines. Also there is nothing in your for loop so the if statement always checks if 0*0 == num.
This looks like it may be a homework question so I won't give a full answer for you but think about how you can make this more efficient.
If you have found an integer number that matches do you need to keep going?
Do you need to check every number? (a starting point may be following the principles of a binary search)
I ended up like this:
import java.util.Scanner;
class Q3{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int num = 0;
int a = 0;
int b = 0;
System.out.println("Type a number to check if it has square");
num = sc.nextInt();
for(a = 1;a<num;a++){
if (a*a == num){
b = 1;
break;
}
}
if(b==1){
System.out.println("Perfect Square");
}
else {
System.out.println("Not ok");
}
}
}
Thanks for support !

How to split a string up and save it to a variable if it is valid?

I'm having some problems splitting a string that is read in from an input file, making sure it's valid, then saving it to a variable.
Let's say this is the first string:
12345 5 59.28
I would want to split the 12345, 5, and 59.28.
After verifying that they are the correct format ( 00000-99999, 0-5, 000.00 0 100.00 ), I would then assign it to a variable.
My main two obstacles are that I CANNOT use arrays in this program, so I'm not sure how to split the string. I have tried just pulling each section as an int, but that doesn't seem to work.
My other problem is that I'm not sure how to validate it. Would I be using something like this:
//Assuming I have a scanner set up and a class, method declared
//Declare variables
int numbers;
int studentID;
while(fileInput.hasNext())
{
numbers = fileInput.nextInt(); //Not sure how to pull a part of the string
}
//Used to validate that it is within the range
if(numbers < 00000 || numbers > 99999)
{
studentID = numbers;
}
I am a beginner at Java so please do excuse my confusion.
If you know what the structure of the file is, for example if it's always formatted like this:
int int double
Then you can simply callnextInt(), nextInt(), and then nextDouble() to parse the data from it that way.
Maybe something like this
do
{
num1 = scanner.nextInt();
num2 = scanner.nextInt();
num3 = scanner.nextDouble();
} while (scanner.hasNextInt());
And do that in order to collect all of your data, but you'll likely need lots of variables if you have any substantial amount of data you're reading in
Or if there's bad data sometimes with it's correct data immediately after it you could so something like this to skip over the bad one, even though it's not very pretty
do
{
if (scanner.hasNextInt())
{
num1 = scanner.nextInt();
}
else
{
scanner.next() // move past whatever bad data there was
num1 = scanner.nextInt();
}
if (scanner.hasNextInt())
{
num2 = scanner.nextInt();
}
else
{
scanner.next() // move past whatever bad data there was
num2 = scanner.nextInt();
}
if (scanner.hasNextDouble())
{
num3 = scanner.nextDouble();
}
else
{
scanner.next() // move past whatever bad data there was
num3 = scanner.nextDouble();
}
} while (scanner.hasNext());
I think your teachers give this assignment to practice your if-else condition or switch statement and for loop(fundamental) skills.
Here what I did, this may be not completely match with your assignment question but using this you can get complete idea and think of a way to reduce this. Hey! because of we are not here to do your assignment. you have to tackle with your problem and get familiar with those.
Try to understand these, do changes look what happen:
public static void main(String[] args) {
Scanner fileInput = new Scanner(System.in);
//Declare variables
String numbers = "";
String firstNum = "";
String secondNum = "";
String thirdNum = "";
int studentID = 0;
int secondDigit = 0;
double thirdDigit = 0;
System.out.print("Input: ");
numbers = fileInput.nextLine();
int firstIndex = 0;
int secondIndex = 0;
int thirdIndex = 0;
firstIndex = numbers.indexOf(" ");
if(firstIndex <= 4){
System.out.println("Number should be 5");
}else{
firstNum = numbers.substring(0, firstIndex);
numbers = numbers.substring(firstIndex+1);
studentID = Integer.parseInt(firstNum);
if(studentID > 0 && studentID < 99999){
System.out.println("First num: " +firstNum);
}else{
System.out.println("first digits not in a range ");
}
}
secondIndex = numbers.indexOf(" ");
if(secondIndex == 0){
System.out.println("no number");
}else{
secondNum = numbers.substring(0, secondIndex);
numbers = numbers.substring(secondIndex+1);
secondDigit = Integer.parseInt(secondNum);
if(secondDigit >= 0 && secondDigit <= 5){
System.out.println("Second num: " +secondNum);
}else{
System.out.println("second digit not in a range ");
}
}
thirdIndex = numbers.length();
if(thirdIndex < 3){
System.out.println("3 numbers should be there");
}else{
thirdNum = numbers.substring(0, thirdIndex);
thirdDigit = Double.parseDouble(thirdNum);
if(thirdDigit >= 0 && thirdDigit <= 100){
System.out.println("third num: " +thirdNum);
}else{
System.out.println("third digit not in a range ");
}
}
}
I'm not going to explain this also. You have to try, if you have any problem after tackling with this code. ask any question in comment.
Hope this will help!
Try this. Invalid formats will throw an exception during the next method call.
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner in = new Scanner("12345 5 59.28");
in.useDelimiter(" "); // reads per space
String next = in.next("\\d{5}"); // reads next 5 digits
int numbers = Integer.valueOf(next);
System.out.println(numbers);
next = in.next("\\d{1}"); // reads next 1 digit
int studentId = Integer.valueOf(next);
System.out.println(studentId);
next = in.next("\\d{2}\\.\\d{2}"); // reads next a decimal with two digits before and after point
float floatingNumbers = Float.valueOf(next);
System.out.println(floatingNumbers);
}
}
<script src="//repl.it/embed/IWzC/0.js"></script>

Code Fails to Return Integer Value From Method (Java/Eclipse)

I have been scouring this site and others for the last two days, and thus am aware of the overwhelming amount of preexisting questions similar to this one. However, having only started programming three or four weeks ago, I am unable to make sense of any of them and their threads. Considering this, I have an issue that to the more experienced likely possesses a painfully basic and straightforward solution.
Using Eclipse, I must create a program which does the following:
Reads in two numbers (integers)
Contains a method that takes the two integers as parameters and returns the larger of the two.
Contains another method that is called from main() takes the larger number returned by the method in (2) as a parameter and returns the last digit.
Prints the two values returned by the methods in (2) and (3).
The code I have created (displayed below) successfully reads in the user input, but fails to print out both the larger integer and the larger integer's last digit. It instead prints out "0". This is what is printed out to the console:
Enter First Integer: (Entered Integer)
Enter Second Integer: (Entered Integer)
Larger Integer: 0
Last Digit: 0
I believe that the code should function correctly, save for the fact that values determined inside the methods are not being returned to the main. No error messages are being displayed by Eclipse, which leads me to believe that the issue lies within my return statements. Any suggestions or solutions are welcomed and desired. Thank you.
import java.util.Scanner;
public class thursdayWork{
//Determines larger integer and returns it.
public static int processAndReturn(int int1, int int2, int answer){
answer = Math.max(int1, int2);
return answer;
}
//Determines last digit of integer and returns it.
public static int processLargerInt(int answer, int lastDigit){
if((answer >= 0) && (answer < 10))lastDigit = (answer % 10);
else if((answer >= 10) && (answer < 100))lastDigit = (answer % 100);
else if((answer >= 100) && (answer < 1000))lastDigit = (answer % 1000);
else if((answer >= 1000) && (answer < 10000))lastDigit = (answer % 10000);
else System.out.print("Pick smaller numbers.");
return lastDigit;
}
//Calls methods and prints returned values.
public static void main(String[] args){
Scanner console = new Scanner(System.in);
int int1;
int int2;
int answer = 0;
int lastDigit = 0;
System.out.print("Enter First Integer: ");
int1 = console.nextInt();
System.out.print("Enter Second Integer: ");
int2 = console.nextInt();
processAndReturn(int1, int2, answer);
System.out.println("Larger Integer: " + answer);
processLargerInt(answer, lastDigit);
System.out.print("Last Digit: " + lastDigit);
}
}
Instead of passing the answer as a param to both the methods, you should have it returned from the method. You should read more about pass by value vs pass by reference.
public static void main(String[] args) {
// Your scanner code here.
int answer = processAndReturn(int1, int2);
System.out.println("Larger Integer: " + answer);
int lastDigit = processLargerInt(answer);
System.out.print("Last Digit: " + lastDigit);
}
public static int processAndReturn(int int1, int int2){
return Math.max(int1, int2);
}
public static int processLargerInt(int answer) {
return answer % 10;
}
Your problem is in how you deal with processAndReturn. Java passes primitives (like int) by value. Meaning that when you give answer to the method processAndReturn it actually hands the method the value of the variable, so any changes you make to it aren't present where you called it from. The way to get around this is by using the return value of processAndReturn
You should modify that line to be something like this:
int answer = processAndReturn(int1, int2);
And you'll need to modify processAndReturn to only take two arguments.
that would look something like this:
static int processAndReturn(int int1, int int2){
return Math.max(int1, int2); //Note: you can just replace a call to this
// With a call to max, meaning it's pointless
}
You'll need to do something similar for processLargerInt as well.
On an unrelated note, this has nothing to do with eclipse. That is your development environment. This has to do with java, so it wouldn't matter what you were developing it in.

Java method won't return answer in my LCM program

So what this program does is take two numbers as input using the Scanner class, and calculates the lowest common multiple of those two numbers. Everything seems to be working, except the lcm method won't return anything. I may have messed something up with my 'break' statements, but I didn't know any other way to get out of the if statement that is nested in a while loop. One more question: Is using a while(True) loop good practice or bad practice? Because I've seen lots of mixed opinions on it. If anyone has any better alternatives to while(True) loops I'd be happy to hear them. Thank you!
// LCM Calculator
// Author: Ethan Houston
// Language: Java
// Date: 2013-12-27
import java.io.*;
import java.util.Scanner;
public class lcm {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("This is a LCM calculator\n");
System.out.println("Enter your first number: ");
int firstNumber = scanner.nextInt();
System.out.println("Enter your second number: ");
int secondNumber = scanner.nextInt();
lcm(firstNumber, secondNumber);
}
public static int lcm(int one, int two) {
int counter = Math.min(one, two);
int initialCounter = counter;
boolean running = true;
while (running) {
if (counter % one == 0 && counter % two == 0) {
break;
} else {
counter += initialCounter;
}
}
return counter;
}
}
You do return something, you're just not printing it. Just try:
System.out.println(lcm(firstNumber, secondNumber));
You are not printing the returned value
System.out.println(lcm(firstNumber, secondNumber));
As you had written,
lcm(firstnumber, secondnumber);
this method will return an int type value, but in your code, you are not obtaining the returned value in any variable.
So, you should write like this :
int variable=lcm(firstnumber, secondnumber);

How to sort the array list?

Hey Guys. thanx for the major help regarding my obstacles.
What my problem this time is, how can I sort the array list that is provided in my code basically dont know WhatI need to add in the provied code below, just to simplyfive it I got 3 arraylist that i want to make them into one arraylist, so they can be sorted in amont of guesses and tries( if 2 players have the same guesses then the time should determine) .
Pretty hard to explain it but i tried my best.............the best thing is to run it then you will figure it what whats the issue is?
Here is the code:
import java.util.*;
import java.util.Scanner.*;
import java.util.ArrayList.*;
public class Main {
public static String ToString(int a, double b, String c)
{
String aS = Integer.toString(a);
String bS = Double.toString(b);
String scoreList = (aS + "\t\t" + bS + "\t\t" + c);
return scoreList;
}
private static void start() {
int tries = 0 ;
int guess = -1;
String name ;
String quit = "quit";
String y = "yes";
String n = "no";
String currentGuess;
String another = ("y") ;
Scanner input = new Scanner (System.in);
ArrayList<String> scores = new ArrayList<String>();
boolean a=false;
do {
a=false;
int answer = (int) (Math.random() * 1000 + 1) ;
System.out.println( " Welcome to Guessing Game " ) ;
System.out.print("Please enter a number between 1 and 1000 : ");
currentGuess = input.nextLine();
long startTime = System.currentTimeMillis();
do
{
if (currentGuess.equalsIgnoreCase(quit))
{
System.out.println("Leaving Us So Soon?");
System.exit(0);
}
try {
guess = Integer.parseInt(currentGuess);
} catch (NumberFormatException nfe)
{
System.out.println(" Dude Can You Read, Only Digits ");
currentGuess = input.nextLine();
}
if (guess < 1 || guess > 1000)
{
System.out.println("Stupid Guess I Wont Count That.");
currentGuess = input.nextLine();
}
if (guess < answer )
{
System.out.println("too low "+answer);
currentGuess = input.nextLine();
tries++;
}
else if(guess > answer )
{
System.out.println("too high "+answer);
currentGuess = input.nextLine();
tries++;
}
else if (guess == answer)
{
//stop stop watch
long endTime = System.currentTimeMillis();
//calculate game time
long gameTime = endTime - startTime;
System.out.println("You Rock Dude, Good Job!");
System.out.println("You guessed " + tries + " times in " + (int)(gameTime/1000) + " seconds.");
System.out.println("Please enter your name.");
name = input.nextLine();
//create score object
String TOString =ToString(tries, gameTime, name);
//add score to arrayList
scores.add(TOString);
boolean s = false ;
while (s==false)
{
System.out.print("Want to go again?(y/n).....");
currentGuess = input.nextLine();
if (currentGuess.matches("y"))
{
System.out.println("HighScore: \nGuess \t Time in milisec\tName");
//print out high score list
for (int i = 0;i < scores.size(); i++)
{
System.out.println(scores.get(i));
}
// Main.start
s=true;
}
//if user doesn't want to play again
if (currentGuess.matches("n"))
{
System.out.println("HighScore:\nGuess \tTime in milisec\tName");
//print out high score list
for (int i = 0;i < scores.size(); i++)
{
System.out.println(scores.get(i));
}
System.out.println("Thanx For Playing.");
a=true;
s=true;
System.exit(0);
}
}
}
} while (guess != answer);
}while(a==false);
}
public static void main(String[] args) {
// ArrayList<Score> scores = new ArrayList<Score>();
Main.start();
}
}
Use Collections.sort() and make sure your class implements Comparable or use something like this:
Collections.sort(list, new Comparator<T>() {
public int compare(T o1, T o2) {
return o1.compareTo(o2);
}});
You can use something like input.nextInt() to read in the next integer instead of the next String. I can see no reason why you are storing Strings instead of ints in your code. Then you can use what everyone else has suggested to combine the lists and/or sort them.
I also think you should do some more reading by yourself. Some of the questions you've asked in your comments are answered in the Java documentation.
When someone posts a suggestion, at the very least look it up in the API and try to understand it. People won't be giving you all the code here, they will just give you hints that you need to follow.
To sort an ArrayList you can use the Collections.sort() method; either with only a List of Comparable elements or with a Comparator.
This is the simplest way.
In your case Collections.sort(scores) will do the thing.
To sort a list, use java.util.Collections.sort( list ).
To make one list out of three, you can use alist.addAll(anotherList). Then sort aList as suggested by Collin Hebert.
I helped to answer this in your previous post. However, I will add it here as well. I think you may want a List instead of a list of Strings. This will allow you to sort on the number of tries the end user has attempted, in a natural way. In addition to the other answers here, the simplest way is then to make a call to Collections.sort(list)
Additionally the toString() method is used for debugging purposes, or to provide human readable information. It shouldn't be used to create objects in the way that you are utilizing it. Just my .02
If you absolutely require a list to be sorted at all times, don't use an ArrayList, use a PriorityQueue. It can be constructed to use the content's natural sort order (i.e. via the Comparable interface on each object), or via a Comparator. The advantage of PriorityQueue is it is always sorted even after new items are added.

Categories