patternjavaMinor
Bear and Candies Game
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;
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
You can rewrite this as
With
This saves having to separate declaration and initialization of the variable. Now you can do both in one line.
I prefer the name
You don't need to jump through hoops to get an integer with a
Don't overcomplicate things
You don't need
This saves you two variables and a loop and gives the same result.
Note that you could also drop down to
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.
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.