HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Bear and Candies Game

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
andbeargamecandies

Problem

I am trying to improving my Java skills and I've been doing various different projects/challenges which I usually am able to complete. I unfortunately never have my code reviewed so while my code may work, I would love to hear ways to do things better. I went on Codechef and solved one of the problems and added some basic error handling in addition to what the problem asked. I tried to write the code as clearly as possible to avoid unnecessary comments.

Main.java

```
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {

static List maxEatingCaps_Limark = new ArrayList<>();
static List maxEatingCaps_Bob = new ArrayList<>();

public static void main(String[] args) {

setUp();
Bear Limak = new Bear(maxEatingCaps_Limark,"Limak");
Bear Bob = new Bear(maxEatingCaps_Bob,"Bob");
Bear.startEating(Limak,Bob);

}

public static void setUp() {
int numOfTestCases = 0;
Scanner input = new Scanner(System.in);
System.out.println("Enter number of test cases");

try {
numOfTestCases = Integer.parseInt(input.nextLine().trim());
}
catch (NumberFormatException e) {
System.err.println("You must enter an number" );
System.exit(1);
}

boolean validInput = false;
for (int i = 0; i < numOfTestCases ; i++) {
validInput = false;

while (!validInput)
try {

String maxEatingInput = input.nextLine();
String[] individualEatingCaps = maxEatingInput.trim().split("\\s+");
maxEatingCaps_Limark.add(Integer.parseInt(individualEatingCaps[0]));
maxEatingCaps_Bob.add(Integer.parseInt(individualEatingCaps[1]));
validInput = true;

} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
System.err.println("Enter in the form: INTEGER:(Limark's Max Eating Capacity) INTEGER:(Bob's Max Eating Capacity)");
validInput = false;

Solution

Helper methods

int  numOfTestCases = 0;
    Scanner input = new Scanner(System.in);
    System.out.println("Enter number of test cases");

    try {
        numOfTestCases = Integer.parseInt(input.nextLine().trim());
    }
    catch (NumberFormatException e) {
        System.err.println("You must enter an number" );
        System.exit(1);
    }


You can rewrite this as

Scanner input = new Scanner(System.in);
    System.out.println("Enter number of test cases");

    int remaining = inputInteger(input);
    input.nextLine();


With

public static void inputInteger(Scanner input) {
    try {
        return input.nextInt();
    } catch (NumberFormatException e) {
        System.err.println("You must enter a number" );
        System.exit(1);
    }
}


This saves having to separate declaration and initialization of the variable. Now you can do both in one line.

I prefer the name remaining to numOfTestCases. Why may become clearer when you see how I use it.

You don't need to jump through hoops to get an integer with a Scanner. There's a method just for that.

Don't overcomplicate things

boolean validInput = false;
    for (int i = 0; i < numOfTestCases ; i++) {
        validInput = false;

        while (!validInput)
            try {

                String maxEatingInput = input.nextLine();
                String[] individualEatingCaps = maxEatingInput.trim().split("\\s+");
                maxEatingCaps_Limark.add(Integer.parseInt(individualEatingCaps[0]));
                maxEatingCaps_Bob.add(Integer.parseInt(individualEatingCaps[1]));
                validInput = true;

            } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
                System.err.println("Enter in the form: INTEGER:(Limark's Max Eating Capacity) INTEGER:(Bob's Max Eating Capacity)");
                validInput = false;

            }

    }

}


You don't need validInput. Consider

while (remaining > 0) {
        try {
            String maxEatingInput = input.nextLine();
            String[] individualEatingCaps = maxEatingInput.trim().split("\\s+");
            maxEatingCaps_Limark.add(Integer.parseInt(individualEatingCaps[0]));
            maxEatingCaps_Bob.add(Integer.parseInt(individualEatingCaps[1]));
            remaining--;
        } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
            System.err.println("Enter in the form: INTEGER:(Limark's Max Eating Capacity) INTEGER:(Bob's Max Eating Capacity)");
        }
    }


This saves you two variables and a loop and gives the same result.

Note that you could also drop down to

while (remaining > 0) {
        try {
            maxEatingCaps_Limark.add(input.nextInt());
            maxEatingCaps_Bob.add(input.nextInt());
            remaining--;
        } catch (NumberFormatException e) {
            System.err.println("Enter in the form: INTEGER:(Limark's Max Eating Capacity) INTEGER:(Bob's Max Eating Capacity)");
        }
    }


But this doesn't enforce the two numbers per line requirement. Up to you if you care.

Equations over iteration

You don't have to iterate through the candy. You can do the quadratic formula instead.

$$\frac{(n + 1)^2}{4} = m$$

Where \$n\$ is the number of candies that first bear eats and \$m\$ is the maximum for that bear. Solving for \$n\$ gives

$$n = 2\sqrt{m} - 1$$

Rounding down to an odd integer gives the last number of candies that bear can eat. Add 2 to give the first number that it can't eat. Now do the equivalent for the second bear.

$$n(n+1) = m$$

And the quadratic formula gives

$$n = \frac{-1 \pm \sqrt{1 + 4m}}{2}$$

Negative numbers aren't meaningful here, so

$$n = \frac{\sqrt{4m + 1} - 1}{2}$$

Round down to an even integer to get the last number of candies that can be eaten.

Whoever gets farther wins.

Now you just have to turn those equations into Java.

Code Snippets

int  numOfTestCases = 0;
    Scanner input = new Scanner(System.in);
    System.out.println("Enter number of test cases");

    try {
        numOfTestCases = Integer.parseInt(input.nextLine().trim());
    }
    catch (NumberFormatException e) {
        System.err.println("You must enter an number" );
        System.exit(1);
    }
Scanner input = new Scanner(System.in);
    System.out.println("Enter number of test cases");

    int remaining = inputInteger(input);
    input.nextLine();
public static void inputInteger(Scanner input) {
    try {
        return input.nextInt();
    } catch (NumberFormatException e) {
        System.err.println("You must enter a number" );
        System.exit(1);
    }
}
boolean validInput = false;
    for (int i = 0; i < numOfTestCases ; i++) {
        validInput = false;

        while (!validInput)
            try {

                String maxEatingInput = input.nextLine();
                String[] individualEatingCaps = maxEatingInput.trim().split("\\s+");
                maxEatingCaps_Limark.add(Integer.parseInt(individualEatingCaps[0]));
                maxEatingCaps_Bob.add(Integer.parseInt(individualEatingCaps[1]));
                validInput = true;

            } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
                System.err.println("Enter in the form: INTEGER:(Limark's Max Eating Capacity) INTEGER:(Bob's Max Eating Capacity)");
                validInput = false;

            }

    }

}
while (remaining > 0) {
        try {
            String maxEatingInput = input.nextLine();
            String[] individualEatingCaps = maxEatingInput.trim().split("\\s+");
            maxEatingCaps_Limark.add(Integer.parseInt(individualEatingCaps[0]));
            maxEatingCaps_Bob.add(Integer.parseInt(individualEatingCaps[1]));
            remaining--;
        } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
            System.err.println("Enter in the form: INTEGER:(Limark's Max Eating Capacity) INTEGER:(Bob's Max Eating Capacity)");
        }
    }

Context

StackExchange Code Review Q#162632, answer score: 4

Revisions (0)

No revisions yet.