How Do I exit a loop and afterwards print Text - java

I've been trying to simulate somehting like the lottery.
I told java to run the while loop until the variable playCount equals 1000. Here is my code:
package problemset.leveltwo;
import java.util.*;
public class PlaySimLoop {
public static void main(String[] args) {
Random random = new Random();
int High = 100;
int Low = 10;
int playCount = 0;
int winCount = 0;
int loseCount = 0;
while (playCount > 1000) {
int yourNumber = random.nextInt(High - Low) + Low;
int winningNumber = random.nextInt(High - Low) + Low;
if (yourNumber == winningNumber) {
winCount = (winCount + 1);
}
if (yourNumber != winningNumber) {
loseCount = (loseCount + 1);
}
playCount = (playCount + 1);
if (playCount == 1000) {
break;
}
System.out.println("You Won " + winCount + " Times");
System.out.println("You Lost" + loseCount + " Times");
}
}
}
After I run the program it prints no information or statistics in the console of java eclipse. It says " PlaySimLoop (java application)" followed by a route to where it is saved on my computer.
Help is appreciated!
Tyler

Your loop condition is wrong
while (playCount > 1000) {
Will run while the variable is GREATER than 1000. But it starts at being 0... so the loop will never run. You probably want:
while (playCount < 1000) {
Which will run while the variable is less than 1000.
Furthermore, this blurb:
if (playCount == 1000) {
break;
}
Is unneccessary. The loop condition as defined in this answer will automatically stop after 999. Meaning this condition could never be true if you simply increment the counter by 1 each time as you're doing.

You might want to move the System.out.println out of the while loop.
someNumber = (someNumber + 1) can be written as someNumber += 1 or using the postfix increment operator: someNumber++. Instead of using another if condition you can use an else block.
if (yourNumber == winningNumber) {
winCount++;
} else {
loseCount++;
}
loseCount could also be calculated at the end from playCount - winCount.

Related

While loop not looping after script finishes

I have 2 while loops, the first while loop is supposed to take the scanner input and loop around. Once the script is finished for the second while loop, my code stops.
while (timesLooped < loopTimes) {
while (loss < 2) {
Thread.sleep(10);
Random randomGenerator1 = new Random();
Random randomGenerator2 = new Random();
int n = randomGenerator1.nextInt(max);
int b = randomGenerator2.nextInt(max);
if (n == 1 && b == 1) {
loss = loss + 2;
System.out.println("You got snake eyes and lost!");
} else {
score = score + n + b;
}
System.out.println("You got: " + n + b);
System.out.println("Your new score is: " + score);
}
timesLooped = timesLooped + 1;
}
loss is never reset. After it completes the inner while loop once, it never runs it again since the condition always stays false. You add an additional print statement to confirm this is what happens:
while (timesLooped < loopTimes) {
// Once this finishes loss remains the same
while (loss > 2) {
// Etc...
}
// Add a print statement so we can observe it running multiple times.
System.out.println("Ran outer loop!");
// You need to reset loss after running the loop
// loss = 0;
timesLooped = timesLooped + 1;
}

Does Java have a limit on loop cycles?

I solved the Project Euler problem #14 https://projecteuler.net/problem=14 on Java, but when I run it in Powershell, it stops iterating at exactly i = 113383 every time. I rewrote the solution on python, and it works perfectly fine, albeit slowly. According to my (identical) python solution, the answer is that the number that produces the longest chain is 837799 and the chain is 524 operations long.
Why does the Java solution not finish the for-loop? Is there some kind of limit in Java on how long it can stay in a loop? I cannot come up with any other explanation. Java code below. I wrote the System.out.println(i) there just to see what is going on.
class ProjectEuler14 {
public static void main(String[] args) {
int largestNumber = 1;
int largestChain = 1;
int currentNumber;
int chainLength;
for (int i = 2; i < 1000000; i++) {
System.out.println(i);
currentNumber = i;
chainLength = 0;
while (currentNumber != 1) {
if (currentNumber % 2 == 0) currentNumber /= 2;
else currentNumber = 3 * currentNumber + 1;
chainLength++;
}
if (chainLength > largestChain) {
largestChain = chainLength;
largestNumber = i;
}
}
System.out.println("\n\nThe number under million that produces the "
+ "longest chain is " + largestNumber +
" and the chain's length is " + largestChain);
}
}
It's not the for loop. It's the while loop. The condition currentNumber != 1 is always true; forever.
In java, an int is specifically defined as an integral number between -2^31 and +2^31 -1, inclusive, and operations 'roll over'. try it!
int x = 2^31 -1;
x++;
System.out.println(x);
this prints a large negative number (in fact, precisely -2^31).
It's happening in your algorithm, and that's why it never finishes.
A trivial solution is to 'upgrade' to longs; they are just as fast, really (yay 64-bit processors!) and use 64 bits, thus giving them a range of -2^63 to +2^63-1.
Python sort of scales up its numbers into slowness silently, java makes different choices (and, for crypto and other purposes, that rollover thing is in fact desired).
If you want to go even further, you can always use BigInteger, which grows as much as you need forever (becoming slower and taking more memory as it goes).
To know rollover occurred, the 3* operation would then result in a number that is lower than the original, and you can check for that:
replace:
else currentNumber = 3 * currentNumber + 1;
with:
else {
int newNumber = currentNumber * 3 + 1;
if (newNumber < currentNumber) throw new IllegalStateException("Overflow has occurred; 3 * " + currentNumber + " + 1 exceeds ints capacities.");
currentNumber = newNumber;
}
and rerun it. You'll see your app nicely explain itself.
The currentNumber is exceeding size of int, use long instead.
Do you hava problem overflow int.
Change int to long.
long largestNumber = 1;
long largestChain = 1;
long currentNumber;
long chainLength;
for (int i = 2; i < 1000000; i++) {
//System.out.println(i);
currentNumber = i;
chainLength = 0;
while (currentNumber != 1) {
//System.out.println("# = " + currentNumber);
if (currentNumber % 2 == 0) {
currentNumber /= 2;
} else {
currentNumber = (3 * currentNumber) +1 ;
}
chainLength++;
}
// System.out.println("################################ " + i);
if (chainLength > largestChain) {
largestChain = chainLength;
largestNumber = i;
}
}
System.out.println("\n\nThe number under million that produces the "
+ "longest chain is " + largestNumber
+ " and the chain's length is " + largestChain);

Why can't I enter the while loop?

class Labo21
{
public static void main(String [] arguments){
int n;
int i;
double somme;
System.out.print("Positive number: ");
n = Clavier.lireInt(); //keyboard
if( n <= 0){
System.out.print("ERROR");
}else{
i = 2;
somme = 1;
while (n <= i){
somme = somme + 1.0 / i;
i = i + 1;
}
System.out.print("Result: " + somme);
}
}
}
I try to know why I cannot enter the while loop.
This code has a problem with its mentality. You are lucky that it is not going into the loop though. If it so, it would run without stopping and you cannot understand it.
BECAUSE: in your code you say the condition of while loop is i should be equal to or greater than n. I guess Clavier.lireInt(); getting value from user. So if user enters 1 condition will be while( 1 <= 2) then it will go through the while loop. Increment the i, then i will be 3 again greater than n, increment i then 4 will be greater than n. It will go like that.
I thing your condition should be :
while(n>=i)
Then you can enter n as 5 and count i = 2 to 5.
Am I correct ?
Your number needs to be greater than 0 based on your if condition. To get into the while loop, your number needs to be less than or equal to 2 since you set i equal to 2. So your options are 1 or 2.
With that being said, once you're inside the while loop, you will never be able to exit (you have created an infinite loop) because n will always be less than i. Your i is incrementing by 1 on each loop iteration, and n is never changing, so it will never be greater than i. You should add a terminating condition (some way to exit the loop).
Provide 1 or 2 as Clavier.lireInt() and you will go inside the loop.
Example :
class Labo21 {
public static void main(String[] arguments) {
int n;
int i;
double somme;
System.out.print("Positive number: ");
n = 1; //Clavier.lireInt(); //keyboard
if (n <= 0) {
System.out.print("ERROR");
} else {
i = 2;
somme = 1;
while (n <= i) {
System.out.println("in loop");
somme = somme + 1.0 / i;
i = i + 1;
}
System.out.print("Result: " + somme);
}
}
}

How to determine if a number is a prime in a faster fashion using additional threads?

I have a program which is PrimeNumbers class. It displays if the x is a prime or not. The x is the number being analyzed in the program.
There is a time on how long will the program take to know the answer. x is so big it takes 9 seconds to know the answer. How could the program run faster using more threads? I am having a hard time on getting how to implement thread in this situation.
public class PrimeNumbers {
private static int x = 2147483647;
public static boolean prime= true;
public static void main(String[]args){
long start, end, elapsetime;
start= System.currentTimeMillis();
for(int y=2; y<x; y++){
if(x % y == 0){
prime=false;
System.out.println(y);
break;
}
}
end = System.currentTimeMillis();
elapsetime = end - start;
System.out.println("Prime: " + prime);
System.out.println(elapsetime+ " mill sec " + (elapsetime / 1000
+ " seconds."));
}
}
I'm going to ignore whether you've got the most efficient approach and focus on how your current code could be faster with more threads.
You currently iterate through all the numbers from 2 -> x and perform a simple test. A way to improve performance might be to split this task into Z chunks and start Z threads to perform the tests in parallel.
E.g. if you had two threads, you would have one thread examine 2 -> x/2 and the other examine x/2 + 1 -> x. Each thread should break from its testing if a global (and probably volatile) flag is set to true, which would indicate the other thread has disproved the prime.
Your primality test is very inefficient, you're looping over each number less than x. How can you improve it? This link should be helpful.
A good algorithm would be the AKS test, or Sieve of Eratosthenes. The code below implements one of the algorithms from the wiki article, which is much more efficient than the test you posted.
public static boolean isPrime(long n) {
// http://en.wikipedia.org/wiki/Primality test
if (n <= 3) return n > 1;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i*i <=n; i+=6) {
if (n % i == 0 || n % (i+2) == 0) return false;
}
return true;
}
}
If you intersted for a better algorithm Munyari has already suggested one.
Ignoring this following example can help you how you can make parallely execute an algorithm (even if it is a stupid algorithm)
We need a class which implements Callable interface (similar one to Runnable). It should get the part of the job and calculate it.
public class PrimeChecker implements Callable<Boolean> {
private final long numberToCheck;
private final long start;
private final long end;
public PrimeChecker(long numberToCheck, long start, long end) {
this.numberToCheck = numberToCheck;
this.start = start;
if (end >= numberToCheck) {
this.end = numberToCheck - 1;
}else{
this.end = end;
}
System.out.println("A PrimeChecker with start " + start + " and end " + end + " values to check number "
+ numberToCheck);
}
#Override
public Boolean call() throws Exception {
boolean prime = true;
long current = start;
if (current != 2 && (current % 2 == 0)) {
current = current + 1;
}
for (; current < end; current = current + 2) {
if (numberToCheck % current == 0) {
prime = false;
System.out.println("The number " + numberToCheck + " is divisable with " + current);
return prime;
}
}
return prime;
}
}
It simply start from a number and check if the given number numberToCheck is divisable and continues until it reaches the number end.
In the Main class we have to create multiple PrimeChecker jobs and execute them parallely. For this purpose we use Java's ExecutorService. It creates for us a thread pool. And then we can divide the job on multiple PrimeCheckers. Finally we execute them invokeAll method of ExecutorService. This gives us a Future list, which contains results of each jobs that we executed parallely.
public class Main {
public static boolean prime= true;
public static void main(String[] args) throws InterruptedException, ExecutionException {
long startTime = System.currentTimeMillis();
long numberToCheck = 5333334345L;
int numberOfThreads = 10;
System.out.println("Checking if the number " + numberToCheck + " ...");
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
List<PrimeChecker> primeCheckers = new ArrayList<PrimeChecker>();
long partOfNumber = (long) Math.ceil((double)numberToCheck/ numberOfThreads);
long start = 2 ;
long end = 0;
for(int i = 0; i < numberOfThreads; i++){
end = end + partOfNumber;
primeCheckers.add(new PrimeChecker(numberToCheck, start, end));
start = end+1;
}
List<Future<Boolean>> futures = executor.invokeAll(primeCheckers);
for(Future<Boolean> future : futures){
prime = future.get();
if(prime == false){
break;
}
}
System.out.println("The number " + numberToCheck + " is " + (prime ? "a prime" :"NOT !!!!!!!!!!!!!!!!!!!! a prime") + " number");
long endTime = System.currentTimeMillis();
long elapsetime = endTime - startTime;
System.out.println(elapsetime + " milliseconds");
System.exit(0);
}
}
You can try it with different numbers of threads (see numberOfThreads variable) to see the difference.
I hope it is a useful example for you, to understand multi threading better. (Be careful: It is only a tiny tiny part part of the whole threading theme)
If you do not need to implement the prime check yourself, I would propose to use the API. You can control the certainty, depending on your needs. In the example it is: 1-(1/2)100
public static void main(String[] args) {
BigInteger mersenne = new BigInteger("2").pow(521).add(BigInteger.ONE.negate());
System.out.println("digits of the number: " + mersenne.toString().length());
long start = System.currentTimeMillis();
final int certainty = 100;
boolean isPrime = mersenne.isProbablePrime(certainty);
System.out.println("elapsed millis: " + (System.currentTimeMillis() - start));
System.out.println("isPrime : " + isPrime);
}
edit
Here is an optimised version of the proposed example.
public class PrimeNumbers {
private static int x = 2147483647;
public static boolean prime= true;
public static void main(String[]args){
long start, end, elapsetime;
int divisor = 1;
start= System.currentTimeMillis();
if (x % 2 == 0) {
prime = false;
divisor = 2;
} else {
// - you can use an increment of two
// because you don't need to check
// for a divisor which is a multiple
// of two
// - you don't need to check for any divisor
// which is greater than x/2
for(int y=3; y < x/2; y += 2){
if(x % y == 0){
prime=false;
divisor = y;
break;
}
}
}
end = System.currentTimeMillis();
System.out.println("Prime: " + prime);
if (!prime) {
System.out.println("divisible by: " + divisor);
}
elapsetime = end - start;
System.out.println(elapsetime+ " mill sec " + (elapsetime / 1000
+ " seconds."));
}
}

Loop with Dice rolling program, previous roll and double check

A fairly trivial problem to most I am sure but I can't quite work out how I'm meant to get the previous dice integer to remain the same as the previous roll of die in the program. I think the code is fairly self explanatory and this is such a trivial program I'm kicking myself for not being able to get my head around it.
import java.util.Random;
public class Dice {
public static void main(String[] args) {
Random rand = new Random();
int min = 1;
int max = 6;
int loop = 0;
int diceRollOne = 0;
int diceRollTwo = 0;
int diceTotal = 0;
int prevDiceTotal = 0;
while (loop < 15000) {
loop++;
diceRollOne = rand.nextInt(max - min + 1) + min;
diceRollTwo = rand.nextInt(max - min + 1) + min;
diceTotal = diceRollOne + diceRollTwo;
System.out.println("Dice Roll 1: " + diceRollOne);
System.out.println("Dice Roll 2: " + diceRollTwo);
System.out.println("Dice Total: " + diceTotal);
System.out.println("previous total: " + prevDiceTotal);
prevDiceTotal = diceTotal;
if (diceRollOne == diceRollTwo || diceTotal == prevDiceTotal) {
System.out.println("After " + loop + " loops the");
System.out.println("Numbers Match, YOU GET NOTHING, YOU LOSE, GOOD DAY SIR!");
System.exit(0);
}
}
}
}
The basic idea being 15,000 simulations. Roll two dice. If you roll a double quit. If you roll the same sum in the current roll as the sum of the previous roll then quit. I've tried debugging by printing out the previous dice total but it defaults to zero every time.
You just want to move the prevDiceTotal = diceTotal; to after your if statement.
if (diceRollOne == diceRollTwo || diceTotal == prevDiceTotal) {
System.out.println("After " + loop + " loops the");
System.out.println("Numbers Match, YOU GET NOTHING, YOU LOSE, GOOD DAY SIR!");
System.exit(0);
}
prevDiceTotal = diceTotal;
You have the following:
prevDiceTotal = diceTotal;
if(diceRollOne == diceRollTwo || diceTotal == prevDiceTotal){
As it's written now it guarantees if-expression to be True.
Move the assignment after your if block.
This is where a good IDE can help you. Here is what IntelliJ IDEA (which has a free Community Edition) shows for your code. Note the highlighting of the if() statement along with a description of the problem.
As others have said, move the assignment of prevDiceTotal after the if() block to solve the problem.

Categories