Speeding up Pythogrean triple calculator - java

So far my code runs fine, but I need a way to speed it up. When the user enters max_values to be 25000 it takes about 1.81 seconds and I need it to be less than one second. I tried my best to optimize my triples method but I don't know what else to do.
import java.util.InputMismatchException;
import java.util.Scanner;
public class Pythagorean {
public static void triples(int max_values){
int x = 0;
for(int c = 5; c <= max_values; c++){
int cTwo = c * c;
int b = c - 1;
for (int a = 0;a <= cTwo - b*b;a++){
if (a*a + b*b == cTwo){
x++;
System.out.println(x + ") " + a + " " + b + " " +c);
}
}
}
}
public static void main(String[] args){
System.out.println("--- Pythagorean Triple Generator ---");
System.out.println();
Scanner input = new Scanner(System.in);
int max_value = 0;
System.out.print("Enter max value for c: ");
try{
max_value = input.nextInt();
} catch (InputMismatchException ime) {
input.nextLine();
System.err.println("Error: Input is not an integer.");
System.exit(1);
}
input.close();
long start = System.currentTimeMillis();
triples(max_value);
double elapsed = (System.currentTimeMillis() - start)/ 1000.0;
System.out.println("Searching complete...");
System.out.printf("Elpased time: %.3f\n", elapsed);
}
}

This just ran in 0.999 seconds on my PC.
It uses a single StringBuilder to collect all the output, then does just one println at the end.
public static void triples(final int max_values)
{
int x = 0;
final StringBuilder sb = new StringBuilder(24000);
for (int c = 5; c <= max_values; c++)
{
final int cTwo = c * c;
final int b = c - 1;
final int bTwo = b * b;
final int cTwoLessB = cTwo - bTwo;
for (int a = 0; a <= cTwoLessB; a++)
{
if (a * a + bTwo == cTwo)
{
x++;
sb.append(x);
sb.append(") ");
sb.append(a);
sb.append(" ");
sb.append(b);
sb.append(" ");
sb.append(c);
sb.append("\n");
}
}
}
System.out.println(sb.toString());
}

The bottleneck is most likely System.out.println. Writing to the console often takes time.
for (int a = 0;a <= cTwo - b*b;a++){
if (a*a + b*b == cTwo){
x++;
System.out.println(x + ") " + a + " " + b + " " +c);//Do you really need this?
}
}
Maybe you could store it in a collection and do the printing after the loop is done (or use Stringbuilder as suggested).
Some optimizations:
int multiplyB = b*b ;//multiplication can also be slow.
for (int a = 0;a <= cTwo - multiplyB;a++){
if (a*a + multiplyB == cTwo){
++x;//use preincrement operator
str.append(x ).append(") ").append(a).append( " ").append(b).append(" ").append(c).append("\n");
}
}

Related

How to find factorial and show result of counting in console?

public class Car {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
System.out.println(n+"!="+factorial(n));
}
public static int factorial(int num) {
return (num == 0) ? 1 : num * factorial (num - 1);
}
}
how make this code to text in console 3! = 1*2*3 = 6?
Don't use recursion for this. Besides, it isn't really efficient or necessary.
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int fact = 1;
String s = n + "! = 1";
for (int i = 2; i <= n; i++) {
fact *= i;
s += "*" + i;
}
s += " = ";
System.out.println(s + fact);
There can be many ways to do it e.g. you can build the required string or print the trail while calculating the factorial. In the following example, I have done the former.
As an aside, you should check the input whether it is a positive integer.
import java.util.Scanner;
public class Car {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Enter a positive integer: ");
int n = in.nextInt();
if (n >= 0) {
StringBuilder strFact = new StringBuilder();
int fact = factorial(n, strFact);
if (strFact.length() > 0) {
// Delete the last '*'
strFact.deleteCharAt(strFact.length() - 1);
System.out.println(n + "!= " + strFact + " = " + fact);
} else {
System.out.println(n + "!= " + fact);
}
} else {
System.out.println("This is an invalid input.");
}
}
public static int factorial(int num, StringBuilder strFact) {
int fact;
if (num == 0) {
fact = 1;
} else {
fact = num * factorial(num - 1, strFact);
strFact.append(num + "*");
}
return fact;
}
}
A sample run:
Enter an integer: 3
3!= 1*2*3 = 6

How to output random letters in java and get the total, high score and lowest score?

Basically, I'm trying to output random uppercase letters and the loops go on forever what am I doing wrong?
I've tried other methods using java.util.Scanner for my input dialog but other than that I can't see what's wrong.
import javax.swing.*;
public class SlotMachine {
public static void main (String[] args) {
String HOWN = JOptionPane.showInputDialog ("Enter how many times you are going to play");
int HOW = Integer.parseInt (HOWN);
double counter = 0;
System.out.println("You chose to play " + HOW + " times");
for (int i = 0; i<HOW; i++) {
for (int b = 0; b<3; i++) {
double result = Math.random();
result = Math.round (result );
result = result * ((90 - 65)+1) - 65;
char resultF = (char)result;
counter = counter + result;
System.out.println ("");
System.out.println("you got: " + resultF + " which is " + result + "in ASCII code");
System.out.println("your total is: " + counter);
}
}
}
}
You have done
for (int b = 0; b<3; i++)
instead of the correct
for (int b = 0; b<3; b++)
This should help your loop terminate.

Sum of Numbers (expected output issue)

I am having issues with my program. The point is that the user needs to enter a starting number (ex:1) and an ending number (ex:5), the output should be 1+2+3+4+5=15. I, on the other hand, am getting 1+2+3+4+5+. I am unsure as to how to fix it, any help would be greatly appreciated. Thanks!Also is there anyway to not return null? My program keeps asking me to return it to null.
import java.util.Scanner;
public class SumOfNumbers
{
public String getSum(int start, int end)
{
int sum=0;
Scanner scanner = new Scanner(System.in) ; //Scanner used to get keyboard values
System.out.println("Enter your starting number: ");
start = scanner.nextInt(); //first number
System.out.println("Enter your ending number: ");
end =scanner.nextInt(); //second number
for(int i=start;i<=end;i++)
{
sum=sum+i; //calculating sum
scanner.close();
System.out.print(i + "+");
}
return null;
}
}
You currently output + after every number, instead output the first number and then start looping (but in the loop, output a + before every number). Also, don't forget to output the sum after your loop. Something like
int sum = start;
System.out.print(start);
for (int i = start + 1; i <= end; i++) {
System.out.print("+" + i);
sum += i;
}
System.out.println(" = " + sum);
However, since you apparently need to return this result as a String you should be doing something like
int sum = start;
StringBuilder sb = new StringBuilder();
sb.append(start);
for (int i = start + 1; i <= end; i++) {
sb.append("+").append(i);
sum += i;
}
sb.append("=").append(sum);
// System.out.println(sb.toString());
return sb.toString();
And you should probably be using the start and end values you pass to the function (instead of ignoring them and prompting the user in the function).
I have tried to add both of the outputs together in the return statement by making them into strings but no luck
The code above is logically equivalent to (but more efficient then)
int sum = start;
String result = String.valueOf(start);
for (int i = start + 1; i <= end; i++) {
result = result + "+" + i;
sum = sum + i;
}
result = result + "=" + sum;
// System.out.println(result);
return result;
It could also be written more concisely like
int sum = start;
String result = String.valueOf(start);
for (int i = start + 1; i <= end; i++) {
result += "+" + i;
sum += i;
}
result += "=" + sum;
// System.out.println(result);
return result;
Or, if we're using Java 8+, with lambdas like
StringBuilder sb = new StringBuilder(String.valueOf(start));
int sum = IntStream.rangeClosed(start, end).sum();
IntStream.rangeClosed(start + 1, end).forEach(x -> sb.append("+").append(x));
sb.append("=").append(sum);
// System.out.println(sb);
return sb.toString();
hope this will help
class SumOfNumbers
{
public void getSum(int start, int end)
{
int sum=0;
Scanner scanner = new Scanner(System.in) ; //Scanner used to get keyboard values
System.out.println("Enter your starting number: ");
start = scanner.nextInt(); //first number
System.out.println("Enter your ending number: ");
end =scanner.nextInt(); //second number
for(int i=start;i<=end;i++)
{
sum=sum+i; //calculating sum
scanner.close();
if (i==end) {
System.out.print(i );
}
else {
System.out.print(i + "+");
}
}
System.out.print("="+ sum);
}
}
output
Enter your starting number:
1
Enter your ending number:
15
1+2+3+4+5+6+7+8+9+10+11+12+13+14+15=120
Here is a method that will do what you are asking for:
public String output(int startNum, int endNum) {
String reply = "";
int answer = 0;
for (int x = startNum; x <= endNum; x++) {
if (x == startNum) reply = "" + x;
else if (x == endNum) reply = reply + "+" + x + "=";
else reply = reply + "+" + x;
answer += x;
}
reply = reply + answer;
return reply;
}
Here is the output:
System.out.println(output(1,10));
1+2+3+4+5+6+7+8+9+10=55

Java - Optional loop

This is my code:
/* Linear equation student quiz
* This program creates equations of the form ax + b = c for students to solve.
*/
import java.util.Random;
import java.util.Scanner;
public class MathFunction {
public static void main(String[] args) {
int a, b, c;
double userAnswer, correctAnswer;
int numCorrect = 0;
Random ranNum = new Random();
Scanner input = new Scanner(System.in);
for (int problem = 1; problem <= 10; problem++)
{
a = ranNum.nextInt(2) + 1;
b = ranNum.nextInt(41) - 20;
c = ranNum.nextInt(41) - 20;
System.out.print("\n"+ a + "x + " + b + " = " + c + " ... x = ");
userAnswer = input.nextDouble();
correctAnswer = 1.0 * (c - b) / a;
if (userAnswer == correctAnswer)
{
System.out.println("Correct!");
numCorrect =+ 1;
}
else
{
System.out.println("Sorry, correct answer is " + correctAnswer);
}
}//end for loop
System.out.println("You got " + numCorrect + " out of ten.");
System.out.println("\nWant to do 10 more questions? <y/n>");
}//end main
}//end class
I want to be able to return to the loop if the user enters the character 'y'. The user will be prompted of this option every time they complete 10 of the math problems. Would I use a 'do-while'?
Yes, you should wrap the for loop with a do-while loop that checks if the user entered 'y'.
do {
for (...) {
...
}
System.out.println("You got " + numCorrect + " out of ten.");
System.out.println("\nWant to do 10 more questions? <y/n>");
input.nextLine();
String repeat = input.nextLine();
} while (repeat.equals("y"));
Here what I mean by breaking your program into methods,
/* Linear equation student quiz
* This program creates equations of the form ax + b = c for students to solve.
*/
import java.util.Random;
import java.util.Scanner;
public class MathFunction {
int a, b, c;
double userAnswer, correctAnswer;
int numCorrect = 0;
Random ranNum = new Random();
Scanner input = new Scanner(System.in);
//You function to calculate
public static compute()
{
for (int problem = 1; problem <= 10; problem++)
{
a = ranNum.nextInt(2) + 1;
b = ranNum.nextInt(41) - 20;
c = ranNum.nextInt(41) - 20;
System.out.print("\n"+ a + "x + " + b + " = " + c + " ... x = ");
userAnswer = input.nextDouble();
correctAnswer = 1.0 * (c - b) / a;
if (userAnswer == correctAnswer)
{
System.out.println("Correct!");
numCorrect =+ 1;
}
else
{
System.out.println("Sorry, correct answer is " + correctAnswer);
}
}//end for loop
System.out.println("You got " + numCorrect + " out of ten.");
System.out.println("\nWant to do 10 more questions? <y/n>");
}
public static void main(String[] args) {
// Then start by sking a question like "Ready to staxt Y/N"
//get user responce or user input and if user input is Y then call the compute method else system exit.
if(userAnswer=="Y")
{
compute();
}
else{
//Thanks for participating system closes.
System.exit(0);
}
}//end main
}//end class
Here is the simple solution
String choice = "y";
while(choice.equals("y")){
for (int problem = 1; problem <= 10; problem++)
{
a = ranNum.nextInt(2) + 1;
b = ranNum.nextInt(41) - 20;
c = ranNum.nextInt(41) - 20;
System.out.print("\n"+ a + "x + " + b + " = " + c + " ... x = ");
userAnswer = input.nextDouble();
correctAnswer = 1.0 * (c - b) / a;
if (userAnswer == correctAnswer)
{
System.out.println("Correct!");
numCorrect =+ 1;
}
else
{
System.out.println("Sorry, correct answer is " + correctAnswer);
}
}//end for loop
System.out.println("You got " + numCorrect + " out of ten.");
System.out.println("\nWant to do 10 more questions? <y/n>");
choice = input.nextLine(); // get the input
}
-> Wrap your code in a do while loop.
-> Also use input.nextLine() for reading all user inputs (double value and string "y" or "n"), as switching between input.nextDouble() and input.nextLine() , can sometimes cause errors. Parse the input value to double after user input.
outer: //label
do{
for (int problem = 1; problem <= 10; problem++)
{
a = ranNum.nextInt(2) + 1;
b = ranNum.nextInt(41) - 20;
c = ranNum.nextInt(41) - 20;
System.out.print("\n"+ a + "x + " + b + " = " + c + " ... x = ");
try{
userAnswer = Double.parseDouble(input.nextLine()); //use this to get double input from user
}
catch(NumberFormatException e){
//warn user of wrong input
break outer;
}
correctAnswer = 1.0 * (c - b) / a;
if (userAnswer == correctAnswer)
{
System.out.println("Correct!");
numCorrect =+ 1;
}
else
{
System.out.println("Sorry, correct answer is " + correctAnswer);
}
}//end for loop
System.out.println("You got " + numCorrect + " out of ten.");
System.out.println("\nWant to do 10 more questions? <y/n>");
if(input.nextLine().equalsIgnoreCase("y")){
continue outer; //if user wants to continue
}
else{
break outer; //if user does not want to continue, break out of outer do-while loop
}
}
while(true);

Java count longest possible array

I'm doing a coin toss program, and am trying to determine the longest possible run of heads or tails that were tossed. I already have code for determining if toss is heads or tails, but now need to count longest possible run. Help! Here's my code for the basic program.
public static void coin_toss(char [] toss)
{
int s = 0;
try
{
for (s = 0; s <= toss.length; s++)
{
double flip;
flip = (double)(Math.random());
if (flip < 0.5)
toss[s] = 't';
else
toss[s] = 'h';
}//end of for loop to load array
}
catch (ArrayIndexOutOfBoundsException errorMessage)
{
System.out.println("\nSubscript out of bounds");
System.out.println("Subscript went past the limit of " + toss.length);
System.out.println("Last value of subscript was --> " + s);
System.out.println("-------------------------------------------------");
System.out.println(errorMessage);
System.out.println("-------------------------------------------------");
}
}//end of toss coin
public static double percent_heads (char [] toss)
{
double percent_h;
int heads = 0;
for (int s = 0; s < toss.length; s++)
{
if (toss[s] == 'h')
heads = heads + 1;
}
System.out.println("There were " + heads + " heads results");
percent_h = (double)heads / toss.length;
return (percent_h);
}//end of heads percentage function
public static double percent_tails (char [] toss)
{
double percent_t;
int tails = 0;
for (int s = 0; s < toss.length; s++)
{
if (toss[s] == 't')
tails = tails + 1;
}
System.out.println("There were " + tails + " tails results");
percent_t = (double)tails / toss.length;
return (percent_t);
}//end of tails percentage function
public static void main(String [] args)
{
int num_toss = 0;
double heads, tails;
double percent_t, percent_h;
DecimalFormat percent = new DecimalFormat ("#0.00%");
System.out.print("How many tosses would you like? --> ");
num_toss = GetInput.readLineInt();
char [] toss = new char[num_toss];
System.out.println("You chose " + toss.length + " tosses");
coin_toss(toss);
heads = percent_heads(toss);
tails = percent_tails(toss);
System.out.println("The percentage of heads was --> " + percent.format(heads));
System.out.println("The percentage of tails was --> " + percent.format(tails));
longest_toss(toss);
java.util.Date today = new java.util.Date();
System.out.println("\nProgram terminated at " + today);
System.exit(0);
}//end of main method
}//end of class
There is a method I came up with.
public static void longest_toss(char[] toss){
int longestrun = 0;
int curlongestrun = 0;
char prevrun = toss[0];
for (int s = 1; s < toss.length; s++)
{
if (toss[s] == prevrun) {
curlongestrun++;
}else {
curlongestrun=0;
}
if(curlongestrun>longestrun){
longestrun = curlongestrun;
}
prevrun = toss[s];
}
System.out.println("Longest run is : " + longestrun + " Coin side : " + prevrun);
}
You can get maximum index of the array toss[] as Integer.MAX_VALUE - 8
Here it is less by 8 because, in the source code of java.util.ArrayList class, it is clearly mentioned that, MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8 provided you have sufficient memory to hold the content of array with this much data.
int getLongestHeads(char [] toss){
int longestHeads = 0;
for(char c : toss)
{
if(longestHeads > 0 && c == 'h'){
longestHeads = longestHeads + 1;
}
else{
longestHeads = 0;
}
if(c == 'h' && longestHeads == 0) {
longestHeads = 1;
}
}
return longestHeads;
}

Categories