Java method running very slowly on first run only (Android) - java

I have found that my method called checkForErrors takes around 80x longer to run on the first execution only, and I can't seem to figure out why.
D/guess: adhl
D/checkerror: checking for errors took 4760743ns // first run
D/validity: checking guess validity took 7141114ns
D/guess: agkl
D/checkerror: checking for errors took 61035ns // every other run takes around this long
D/validity: checking guess validity took 732422ns
I have looked through the code and I don't see anything that would take longer on the first run only so I'm stumped.
Button on click listener:
submitBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String Guess = guess_txt.getText().toString();
Log.d("guess", Guess);
if(checkGuessValidity(Guess)){ // <--
submitValidGuess(Guess);
int bulls = game.getBullsAndHits()[0];
int hits = game.getBullsAndHits()[1];
if(!game.gameWon) //if game is not won, submit the guess with bulls and hits
guessSubmittedListener.guessSubmitted(Guess, bulls, hits);
else //if game is won, call gameWon() method
gameEnd();
}
if((game.getCurrentTry() > game.getMaxTries()) && (!Guess.equals(game.getHiddenWord()))) gameEnd(); //if user is out of tries, call gameLost method
triesLeft.setText("Tries Left: " + (game.getMaxTries() - game.getCurrentTry() + 1)); //update tries left on main fragment
guess_txt.setText("");
}
});
checkGuessValidity:
public boolean checkGuessValidity(String Guess){
long start = System.nanoTime();
long start2 = System.nanoTime();
ErrorList Status = checkForErrors(Guess); // <--
long end2 = System.nanoTime();
Log.d("checkerror", "checking for errors took " + (end2 - start2) + "ns");
. . . more code . . .
checkForErrors:
public ErrorList checkForErrors(String Guess){
if(Guess.length() != game.getHiddenWordLength()) return ErrorList.Wrong_Length;
else if(!isValidInput(Guess)) return ErrorList.Invalid_Characters;
else if(!isIsogram(Guess)) return ErrorList.Not_Isogram;
else if(!isLowercase(Guess)) return ErrorList.Not_Lowercase;
else return ErrorList.OK;
}
isValidInput, isIsogram and isLowercase:
public boolean isIsogram(String Guess){
Map<Character, Boolean> map = new HashMap();
for(int i = 0; i < Guess.length(); i++){
if(map.get(Guess.charAt(i)) == null) //if the value for the key (character) is null (has not been changed since map initialization)
map.put(Guess.charAt(i), true); //then set it to true (indicating that it has been seen)
else { //else (if the value at the character HAS been changed since initialization, ie. it has been seen)
Log.d("Character repeated", "" + Guess.charAt(i));
return false; //return false
}
}
return true; //if loop completes no duplicates were found and guess is an isogram
}
public boolean isLowercase(String Guess){
if(Guess.equals(Guess.toLowerCase())) return true;
else return false;
}
public boolean isValidInput(String Guess){
char[] chars = Guess.toCharArray();
for(int i = 0; i < chars.length; i++){
if(!isLatinLetter(chars[i])) return false;
}
return true;
}
public static boolean isLatinLetter(char c) {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
It doesn't seem like any of the methods should be impacted by when they are run, so I don't know why it takes extra long on the first execution. I'm still a beginner to programming so please excuse any poor formatting or horribly optimized code :p .
edit: CPU usage graph: https://prnt.sc/ftjokq

Related

Java expects an "AnnotationName" after a method declaration

I am coding a game in Java, and must create a method inside an enum type that returns whether the player may fill a bottle with liquid or not. The method checks whether the player's inventory contains a bottle, and whether the player is near a liquid.
In the method declaration, I am getting an error that says I need to put an "AnnotationName" after it. I do not know what an "AnnotationName" is, and on all the other methods I have created in the file there are no such errors.
There is also another error at the bottom of the enum on the closing bracket. It says "Please insert '}' to complete ClassBody". I have checked all the curly brackets in the file and they all have matches. I think this error must be tied to the above "AnnotationName" error. I have included the method below, as well as the enum type the method is a part of.
The method by itself:
//the problematic method
#Override
public boolean isAvailable() {
//create var
boolean bottleInInventory = false;
//loop thru junk sublist
for (int i = 0; i < Data.player.sizeOfSubList(0); i++) {
//if current item is a Bottle, bottleInInventory = true; otherwise do nothing
if (Data.player.getItem(ItemType.JUNK, i).getClass() == Bottle.class) {
//set var to true
bottleInInventory = true;
}
//repeat loop until a Bottle is found (or not found)
}
//check if player is near a liquid AND if they have a Bottle in their inventory
//if they satisfy both conditions, return true
try {
if (Data.nearLiquid.get(0) != null && bottleInInventory) { //if index 0 has nothing in it, there must'nt be anything in the other indexes either.
return true;
}
} catch (IndexOutOfBoundsException e) { //if the player is not near any liquids this will happen during the above if statement.
return false;
}
return false; //if player is near a liquid and not in possesion of a Bottle
}
The whole enum:
FILL_BOTTLE("Fill Bottle") {
//this method is not complete
#Override
public void opCode() {
boolean multipleBottles; //if there is more than one bottle or not
ArrayList<Bottle> bottlesInInventory = new ArrayList<Bottle>(); //output of loop
Item currentItem; //used only inside loop
for (int i = 0; i < Data.player.sizeOfSubList(0); i++) { //loop counts how many bottles you have
currentItem = Data.player.getItem(ItemType.JUNK, i);
if (currentItem.getClass() == Bottle.class) {
bottlesInInventory.add((Bottle) currentItem); /* currentItem will always be assigned to a Bottle here,
* but we still need to cast because the
} * variable type is an Item. */
}
//multipleBottles is set to true if the bottlesInInventory list has more than one item in it
if (bottlesInInventory.size() > 1) {
multipleBottles = true;
}
System.out.println("You are currently able to fill your bottle with " + Data.nearLiquid.size() + " liquids near you");
System.out.println();
System.out.println("Here they are:");
for (int i = 0; i < Data.nearLiquid.size(); i++) {
System.out.println((i + 1) + ") " + Data.nearLiquid.get(i).getName());
}
int liquid = Data.intPrompt("Which liquid would you like to fill your bottle with? ");
}
//the problematic method
#Override
public boolean isAvailable() {
//create var
boolean bottleInInventory = false;
//loop thru junk sublist
for (int i = 0; i < Data.player.sizeOfSubList(0); i++) {
//if current item is a Bottle, bottleInInventory = true; otherwise do nothing
if (Data.player.getItem(ItemType.JUNK, i).getClass() == Bottle.class) {
//set var to true
bottleInInventory = true;
}
//repeat loop until a Bottle is found (or not found)
}
//check if player is near a liquid AND if they have a Bottle in their inventory
//if they satisfy both conditions, return true
try {
if (Data.nearLiquid.get(0) != null && bottleInInventory) { //if index 0 has nothing in it, there must'nt be anything in the other indexes either.
return true;
}
} catch (IndexOutOfBoundsException e) { //if the player is not near any liquids this will happen during the above if statement.
return false;
}
return false; //if player is near a liquid and not in possesion of a Bottle
}
},
I've tried adding curly brackets, annotations (#Override), and researched on AnnotationNames but not had any luck. I can't find any documentation on what an AnnotationName is, and the curly brackets and extra annotations just created more errors.
Edit:
Here is a link to the entire file as well as a link to the github repo with my code.
Option.java
Jump The Volcano

For if loop wont loop: any pointers to why that might be?

This is supposed to loop 24 times; it does not, and I'm pretty confused as to why. Please help me various Kenobis out there :
private boolean simpleMove(Board bd)
{
int b = rn.nextInt(3);
for (int i = 0; i < 24; i++) {
if (bd.isVacant(i) && rul.isLegalMove(tigerLocs[b], i)) {
bd.swap(tigerLocs[b],i);
bd.setTiger(i);
tigerLocs[b] = i;
System.out.println(i);
return true;
}
else {
System.out.println(i);
}
}
System.out.println("invalid");
return false;
As the comments point out your loop will execute a maximum of 24 times.
But the return statement inside the if statement may cause it to return 'early'.
It looks like it's some kind of board game thing.
The board appears to have 24 'squares' and it makes the first legal move and returns true.
If it fails to find a legal move, it returns false.
I can't confirm the logic overall but that rationale seems sound:
If there's a move available, take it and return true.
If no move is available, make no move and return false.
If you expected it to continue, even after finding a "valid" move, then simply store the fact that a valid move has been found. This can be done in a separate boolean variable:
private boolean simpleMove(Board bd) {
int b = rn.nextInt(3);
boolean valid = false; // until proven otherwise below
for (int i = 0; i < 24; i++) {
if (bd.isVacant(i) && rul.isLegalMove(tigerLocs[b], i)) {
bd.swap(tigerLocs[b],i);
bd.setTiger(i);
tigerLocs[b] = i;
valid = true;
}
System.out.println(i); // why output HERE when we have a return value?
}
if (!valid) {
System.out.println("invalid"); // why output HERE when we have a return value?
}
return valid;
}
It's unclear if multiple "valid" moves could be found, and whether that would be a problem when you "swap" or not. If there is only ever one possible move, then there would be no need to continue iterating with the for loop; simply return in the body like you were doing.

How could we implement a garage door keeping track of what was its last moving direction?

I am doing the following programming exercise: Killer Garage Door. The statement is:
Situation
You have been hired by a company making electric garage doors.
Accidents with the present product line have resulted in numerous
damaged cars, broken limbs and several killed pets. Your mission is to
write a safer version of their controller software. Specification
We always start with a closed door. The remote control has exactly one
button, with the following behaviour.
If the door is closed, a push starts opening the door, and vice-versa
It takes 5 seconds for the door to open or close completely
While the door is moving, one push pauses movement, another push resumes movement in the same direction
In order to make the door safer, it has been equiped with
resistance-based obstacle detection. When the door detects an
obstacle, it must immediately reverse the direction of movement. Input
A string where each character represents one second, with the
following possible values.
'.' No event
'P' Button has been pressed
'O' Obstacle has been detected (supersedes P)
As an example, '..P....' means that nothing happens for two seconds,
then the button is pressed, then no further events. Output
A string where each character represents one second and indicates the
position of the door (0 if fully closed and 5 fully open). The door
starts moving immediately, hence its position changes at the same
second as the event. Example
..P...O..... as input should yield 001234321000 as output
I have written the following code:
public class Door {
public static String run(String events) {
System.out.println("\n\n\nevents: "+events);
int count = 0;
StringBuilder result = new StringBuilder();
boolean movingUp = false;
boolean movingDown = false;
for(char c : events.toCharArray()){
System.out.println("movingUp: "+movingUp);
System.out.println("movingDown: "+movingDown);
System.out.println("c: "+c);
System.out.println("count: "+count);
System.out.println("result: "+result);
if(c=='.'){
if(movingUp){
result.append(count < 5 ? ++count : 5);
}else if(movingDown){
result.append(count > 0 ? --count : 0);
}else{
result.append(count);
}
}else if(c=='P'){
if(count==5){
movingUp = false;
movingDown = true;
result.append(count > 0 ? --count : 0);
}else if(movingUp){
movingUp = false;
result.append(count);
}else if(movingDown){
movingDown = false;
result.append(count);
}else{
movingUp = true;
result.append(count < 5 ? ++count : 5);
}
}else if(c=='O'){
movingUp = false;
movingDown = true;
result.append(count > 0 ? --count : 0);
}
}
return result.toString();
}
}
I was wondering how could we handle, when there is a pause and then the door resumes again, to be able to keep it going up or down, as it was doing before the pause?
Here are some tests, the ones marked with →, are the ones where the pause or obstacle behaviour fails because of currently the code assumes that after a pause it should go upwards, and after an obstacle it should go downwards.
import static org.junit.Assert.*;
import org.junit.Test;
public class MainTest {
#Test
public void testNormalOperation() {
test("should stay closed unless button is pressed (no buttonpresses)", "..........", "0000000000");
test("should start opening on buttonpress", "P..", "123");
test("should open completely and stay open", "P....", "12345");
}
#Test
public void testPause() {
test("should start opening and pause on second buttonpress", "P.P..", "12222");
test("→ should resume closing on third buttonpress", ".....P......P.P..P....", "0000012345554333321000");
}
#Test
public void testObstacles() {
test("should reverse while opening", "P.O....", "1210000");
test("→ should reverse while closing", "P.O....", "12345554345555");
}
#Test
public void testObstaclePlusPause () {
test("→ should reverse while opening (and allow pause)", "P..OP..P..", "1232222100");
}
#Test
public void testExample() {
test("should start opening and reverse when obstacle", "..P...O.....", "001234321000");
}
private void test(String description, String events, String result) {
assertEquals(description ,result, Door.run(events));
}
}
I have also read:
https://users.cs.jmu.edu/bernstdh/web/common/lectures/summary_state_pattern.php
How could we implement a garage door keeping track of what was its last moving direction?
You're almost there. So in the interest of keeping your code intact I attempted
to introduce as few changes as needed.
However one correction is needed before proceeding - one of your test cases
is not correct, the 2nd test case in testObstacles is not valid.
Was:
test("→ should reverse while closing", "P.O....", "12345554345555");
// in the above the first 'P' would start it "12" and the first "O" should
// immediately reverse it (which would be reversing while opening) "1000"
So assuming the text is correct and the expected result is correct then the input should be:
test("→ should reverse while closing", "P.......P.O....", "12345554345555");
Short answer:
Introduce a boolean which records the previous up or down movement:
boolean lastUp = true; // default to true since we always assume initially CLOSED
The remaining changes are in th 'P' and 'O' case using lastUp:
else if (movingUp)
{
movingUp = false;
lastUp = true; // ADDED
result.append (count);
}
...
else if (movingDown)
{
movingDown = false;
lastUp = false; // ADDED
result.append (count);
}
... and update default case
else
{
movingUp = lastUp; // CHANGED
movingDown = !lastUp; // ADDED
result.append(movingUp ? ++count : --count); // CHANGED
}
And in 'O' case:
{
movingUp = !movingUp; // CHANGED
movingDown = !movingDown; // CHANGED
lastUp = !lastUp; // ADDED
result.append(movingUp ? ++count : --count); // CHANGED
}
Long Answer
Well, the long answer uses a different approach and this is essentially #grodzi 's answer (state then input) which has a great explanation but since it took me so long to enter it the point is moot.
I'll add it since it is in the language of your choice.:
public static class Door
{
enum DoorStates { OPEN, CLOSED, MOVINGUP, MOVINGDOWN, PAUSED }
public static String run (String events)
{
int count = 0;
StringBuilder result = new StringBuilder ();
DoorStates currentState = DoorStates.CLOSED;
DoorStates lastMovingState = DoorStates.MOVINGUP;
for (char c:events.toCharArray ())
{
switch (currentState)
{
case OPEN:
if (c == 'P') {
currentState = DoorStates.MOVINGDOWN;
count--;
}
// do nothing for O and .
break;
case CLOSED:
if (c == 'P') {
currentState = DoorStates.MOVINGUP;
count = 1;
}
// do nothing for O and .
break;
case MOVINGUP: // movingup
if (c == 'P') {
currentState = DoorStates.PAUSED; // paused
} else if (c == 'O') {
currentState = DoorStates.MOVINGDOWN; // movingdown
count--;
} else {
if (count < 5) {
count++;
}
if (count == 5) {
currentState = DoorStates.OPEN; // open
}
}
break;
case MOVINGDOWN:
if (c == 'P') {
currentState = DoorStates.PAUSED; // paused
} else if (c == 'O') {
currentState = DoorStates.MOVINGUP; // movingup
count++;
} else {
if (count > 0) {
count--;
}
if (count == 0) {
currentState = DoorStates.CLOSED;
}
}
break;
case PAUSED:
if (c == 'P') {
currentState = lastMovingState;
count = (currentState == DoorStates.MOVINGUP ? count+1 : count-1);
}
// do nothing for O and .
break;
} // end switch
if (currentState == DoorStates.MOVINGUP ||
currentState == DoorStates.MOVINGDOWN) {
lastMovingState = currentState;
}
result.append (count);
} // endfor
return result.toString();
} // end run
} // door class
An approach by using states.
We can list two trivial ones: closed and opened.
I will name them respectively idleUp, and idleDown.
transitions for idleUp:
P (user pushed the button): so you are now activeUp
transitions for activeUp:
P (user pushed another time): idleUp (keep the direction, but do nothing)
O: activeDown
End (door is fully opened): idleDown
transitions for activeDown:
P: idleDown
O: activeUp
End: idleUp
transitions for idleDown:
P (user pushed the button): so you are now activeDown
Something like graph below.
+----------+ P +--------+
| activeUp +<----->+ idleUp |
+----------+ +--------+
| ^ O ^
|End +---------+ |End
v v |
+----------+ P +------------+
| idleDown +<----->+ activeDown |
+----------+ +------------+
Notice the (somehow elegant) symmetry between activeUp-idleUp and activeDown-idleDown.
In your approach you are char first, then state. In below code we are state first, then char.
Instead of considering four states, we only "code" two: active and idle (but under the hood we indeed have four states, simply conditionned via variable instead of classes)
You sure can use a pattern state, but feels a bit tiresome.
function simu (str) {
let direction = 1 // 1 for up, -1 for down
let pos = 0 // initially closed
let active = false
let out = '' // the return string
for (let c of str) {
if (active) {
if (c === '.') {
pos += 1 * direction
if (pos <= 0 || pos >= 5) {// End
active = false
direction *= -1
}
}
else if (c === 'O') {
direction *= -1
pos += 1 * direction // instant change of direction
}
else if (c === 'P') {
active = false
}
} else { // idle
if (c === 'P') {
active = true
pos += 1 * direction // instant change too
}
}
out += pos
}
return out
}
function test(libel, s, exp) {
const out = simu(s)
if (out != exp) {
throw 'failed '+libel+' got '+out+' expect '+exp
}
console.log('OK', s, '->', out)
}
test("should stay closed unless button is pressed (no buttonpresses)", "..........", "0000000000")
test("should start opening on buttonpress", "P..", "123")
test("should open completely and stay open", "P....", "12345")
test("should start opening and pause on second buttonpress", "P.P..", "12222")
test("→ should resume closing on third buttonpress", ".....P......P.P..P....", "0000012345554333321000")
test("should reverse while opening", "P.O....", "1210000")
test("→ should reverse while closing", "P.......P.O....", "123455554345555") //thx Andy
test("→ should reverse while opening (and allow pause)", "P..OP..P..", "1232222100")
test("should start opening and reverse when obstacle", "..P...O.....", "001234321000")

trying to break out of for loop but keeps going back into it and performing recursive call

I just discovered the project euler website, I have done challenges 1 and 2 and have just started number 3 in java... here is my code so far:
import java.util.ArrayList;
public class IntegerFactorise {
private static int value = 13195;
private static ArrayList<Integer> primeFactors = new ArrayList<Integer>();
private static int maxPrime = 0;
/**
* Check whether a give number is prime or not
* return boolean
*/
public static boolean isPrimeNumber(double num) {
for(int i = 2; i < num; i++) {
if(num % i == 0) {
return false;
}
}
return true;
}
/*Multiply all of the prime factors in the list of prime factors*/
public static int multiplyPrimeFactors() {
int ans = 1;
for(Integer i : primeFactors) {
ans *= i;
}
return ans;
}
/*Find the maximum prime number in the list of prime numbers*/
public static void findMaxPrime() {
int max = 0;
for(Integer i : primeFactors) {
if(i > max) {
max = i;
}
}
maxPrime = max;;
}
/**
* Find all of the prime factors for a number given the first
* prime factor
*/
public static boolean findPrimeFactors(int num) {
for(int i = 2; i <= num; i++) {
if(isPrimeNumber(i) && num % i == 0 && i == num) {
//could not possibly go further
primeFactors.add(num);
break;
}
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
findPrimeFactors(num / i);
}
}
int sumOfPrimes = multiplyPrimeFactors();
if(sumOfPrimes == value) {
return true;
}
else {
return false;
}
}
/*start here*/
public static void main(String[] args) {
boolean found = false;
for(int i = 2; i < value; i++) {
if(isPrimeNumber(i) && value % i == 0) {
primeFactors.add(i);
found = findPrimeFactors(value / i);
if(found == true) {
findMaxPrime();
System.out.println(maxPrime);
break;
}
}
}
}
}
I am not using the large number they ask me to use yet, I am testing my code with some smaller numbers, with 13195 (their example) i get down to 29 in this bit of my code:
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
findPrimeFactors(num / i);
}
}
int sumOfPrimes = multiplyPrimeFactors();
if(sumOfPrimes == value) {
return true;
}
It gets to the break statement then finally the check and then the return statement.
I am expecting the program to go back to the main method after my return statement, but it jumps up to:
findPrimeFactors(num / i);
and tries to finish the iteration...I guess my understanding is a flawed here, could someone explain to me why it is behaving like this? I can't wait to finish it of :) I'll find a more efficient way of doing it after I know I can get this inefficient one working.
You are using recursion, which means that a function will call itself.
So, if we trace what your function calls are when you call return, we will have something like that:
IntegerFactorise.main()
|-> IntegerFactorise.findPrimeFactors(2639)
|-> IntegerFactorise.findPrimeFactors(377)
|-> IntegerFactorise.findPrimeFactors(29) -> return true;
So, when you return in the last findPrimeFactors(), you will only return from this call, not from all the stack of calls, and the execution of the previous findPrimeFactors() will continue just after the point where you called findPrimeFactors().
If you want to return from all the stack of calls, you have to modify your code to do something like that:
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
return findPrimeFactors(num / i);
}
So that when the last findPrimeFactors() returns, all the previous findPrimeFactors() which called it will return too.
I think the problem is that you are ignoring the return value from your recursive call to findPrimeFactors().
Let's walk through this. We start with the initial call to findPrimeFactors that happens in main. We then enter the for loop as it's the first thing in that method. Now let's say at some point we get into the else statement and thus recursively call frindPrimeFactors(num / i). This will suspend the looping, but as this recursive call starts to run you enter the for loop again (remember, the previous loop is merely paused and not finished looping yet). This time around you encounter the break, which allows this recursive call to finish out, returning true of false. When that happens you are now back to the original loop. At this point the original loop continues even if the recursive call returned true. So, you might try something like this:
if (findPrimeFactors(num / i))
return true;
I'm assuming that you need to continue looping if the recursive call returned false. If you should always finish looping upon return (whether true or false) then try this:
return findPrimeFactors(num / i);

Need to convert this for loop to a while loop

I solved a problem recently. But I have this one piece of code where I dont utilize the for loop initialization and condition check. It looks a bit odd that way for a for loop. I want to convert it into a while loop. Please help me do it. I tried many times, but somewhere something is missing.
for(;;current =(current+1)%n){
if(eliminated[current%n]){
continue;
}else{
inkiPinki++;
if(inkiPinki == m){
eliminated[current%n] = true;
printStatus(eliminated, people);
remainingGuys--;
break;
}
}
}
In the above code eliminiated[index] is a boolean.
Edit: Thanks to Geoff who provided me with a solution which I further minimized like this.
while( eliminated[current] || ++inkiPinki != m )
current = (current+1) % n;
eliminated[current] = true;
printStatus( eliminated, people );
remainingGuys--;
All for loops can be converted to while loops using the following pattern:
for (..xxx..; ..yyy..; ..zzz..) {
..aaa..
}
becomes
...xxx...
while (...yyy...) {
..aaa..
..zzz..
}
remember that
for (;;) {
..aaa..
}
is equivalent to
for (nop; true; nop) {
..aaa..
}
where "nop" means no operations.
In your example this makes your loop:
for(;;current =(current+1)%n){
if(eliminated[current%n]){
continue;
}else{
inkiPinki++;
if(inkiPinki == m){
eliminated[current%n] = true;
printStatus(eliminated, people);
remainingGuys--;
break;
}
}
}
equivalent to
// no initialzation needed
while(true) {
//if(eliminated[current%n]){
// continue;
//}else{
if(!eliminated[current%n]){
inkiPinki++;
if(inkiPinki == m){
eliminated[current%n] = true;
printStatus(eliminated, people);
remainingGuys--;
break;
}
}
current =(current+1)%n;
}
From there, you can simplify it further, if you wish.
Try
while( true ) {
if( !eliminated[current] ) {
if( ++inkiPinki == m ) {
break;
}
}
current = (current+1) % n;
}
eliminated[current] = true;
printStatus( eliminated, people );
remainingGuys--;
It should be logically equivalent.
How I would do it:
while (inkiPinki < m) {
if (!eliminated[current % n]) {
inkiPinki++;
if (inkiPinki == m) {
eliminated[current % n] = true;
}
}
if (inkiPinki < m) {
current = (current + 1) % n;
}
}
printStatus(eliminated, people);
remainingGuys--;
This code accomplishes exactly the same thing as your original for loop, except it uses logical tests to determine whether or not it should continue to loop. There's no need for continue or break. If you find yourself using either of these statements, there's probably some refactoring that should be done.
I seem to have an inordinate fondness for using Booleans as integers:
for (;inkiPinki<m; inkPinki += !eliminated[current])
current = (current + 1) %n;
eliminated[current] = true;
printStatus(eliminated, people);
remainingGuys--;
I've also changed current%n to simply current in a couple of places, because the %n is already done where current is incremented, so current should already be reduced modulo n.
If I were doing it, I'd probably change the sense, so instead of eliminated, it was something like remaining:
for (;inkiPinki<m; inkPinki += remaining[current])
current = (current + 1) %n;
remaining[current] = false;
printStatus(remaining, people);
remainingGuys--;

Categories