why are all my array index values set to the same value - java

This portion of my program seems to be giving me a problem:
public static double[] getBonusAmt(boolean[] bonusEligibility, int[] numYrsFlown, double[] bonusAmt) {
bonusAmt = new double[bonusEligibility.length];
double bonus = 0;
for (boolean b : bonusEligibility) {
for (int i : numYrsFlown) {
if (i >= 9 && b == true) {
bonus = 2410.00;
}
else if (i < 9 && i >= 6 && b == true) {
bonus = 1206.00;
}
else if (i < 6 && i >= 2 && b == true) {
bonus = 515.00;
}
else if (i < 2 && b == true) {
bonus = 0.00;
}
}
}
return bonusAmt;
}
Input/Output:
Name: [joe, james]
Years flown: [2, 2]
Miles flown: [45, 43]
Average miles between pilots: 44
Bonus eligibility: [true, false]
Bonus amount: [0.00, 0.00]
Joe should be earning a bonus because his miles flown is greater than the average, but his amount is zero. The expected bonus amount for Joe should be 515.00 because one, he is eligible for a bonus and two, has only flown for 2 years.
Can anyone see why the bonus amount is always zero even if I enter another person that has flown more than the average?

Your method assigns values to the bonus variable but returns a bonusAmt variable, which is never assigned, so its values remain 0.0.
Your nested loops don't make much sense. It looks like you need a single regular for loop, assuming that the i'th index of bonusEligibility array corresponds with the i'th index of the numYrsFlown array.
public static double[] getBonusAmt(boolean[] bonusEligibility, int[] numYrsFlown) {
double[] bonusAmt = new double[bonusEligibility.length];
for (int i = 0; i < bonusEligibility.length; i++) {
if (numYrsFlown[i] >= 9 && bonusEligibility[i]) {
bonus = 2410.00;
}
else if (numYrsFlown[i] < 9 && numYrsFlown[i] >= 6 && bonusEligibility[i]) {
bonusAmt[i] = 1206.00;
}
else if (numYrsFlown[i] < 6 && numYrsFlown[i] >= 2 && bonusEligibility[i]) {
bonusAmt[i] = 515.00;
}
else if (numYrsFlown[i] < 2 && bonusEligibility[i]) {
bonusAmt[i] = 0.00;
}
}
return bonusAmt;
}
BTW, there's no point in passing the bonusAmt array as an argument to the method, since the method assigns to it a reference to a new array.

You forgot to set bonusAmt to the selected bonus value.

Here is a more object oriented way to do what you want. No need to accept this answer as Eran's solution explains your error perfectly ... This is just another way of doing it ...
public class MainApp {
public static void main(String[] args) {
AirMilesCustomer[] customers = new AirMilesCustomer[] {
new AirMilesCustomer("John", true, 2),
new AirMilesCustomer("Jane", true, 5),
new AirMilesCustomer("Sally", true, 7),
new AirMilesCustomer("Bill", false, 10),
new AirMilesCustomer("Stacy", true, 15)
};
for(AirMilesCustomer customer : customers) {
System.out.println(customer);
}
}
}
class AirMilesCustomer {
private String _name;
private boolean _bonusEligibility;
private int _numYrsFlown;
public AirMilesCustomer(String name, boolean bonusEligibility, int numYrsFlown) {
_name = name;
_bonusEligibility = bonusEligibility;
_numYrsFlown = numYrsFlown;
}
public String getName() {
return _name;
}
public boolean isBonusEligibility() {
return _bonusEligibility;
}
public int getNumYrsFlown() {
return _numYrsFlown;
}
public double getBonusAmount() {
double bonus = 0.00;
if (_numYrsFlown >= 9 && _bonusEligibility) {
bonus = 2410.00;
}
else if (_numYrsFlown < 9 && _numYrsFlown >= 6 && _bonusEligibility) {
bonus = 1206.00;
}
else if (_numYrsFlown < 6 && _numYrsFlown >= 2 && _bonusEligibility) {
bonus = 515.00;
}
else if (_numYrsFlown < 2 && _bonusEligibility) {
bonus = 0.00;
}
return bonus;
}
public String toString() {
return "[" + _name + "][" + _numYrsFlown + "][" + _bonusEligibility + "][" + getBonusAmount() + "]";
}
}

Related

Algorithm to find `balanced number` - the same number of even and odd dividers

We define balanced number as number which has the same number of even and odd dividers e.g (2 and 6 are balanced numbers). I tried to do task for polish SPOJ however I always exceed time.
The task is to find the smallest balance number bigger than given on input.
There is example input:
2 (amount of data set)
1
2
and output should be:
2
6
This is my code:
import java.math.BigDecimal;
import java.util.Scanner;
public class Main {
private static final BigDecimal TWO = new BigDecimal("2");
public static void main(String[] args) throws java.lang.Exception {
Scanner in = new Scanner(System.in);
int numberOfAttempts = in.nextInt();
for (int i = 0; i < numberOfAttempts; i++) {
BigDecimal fromNumber = in.nextBigDecimal();
findBalancedNumber(fromNumber);
}
}
private static boolean isEven(BigDecimal number){
if(number.remainder(new BigDecimal("2")).compareTo(BigDecimal.ZERO) != 0){
return false;
}
return true;
}
private static void findBalancedNumber(BigDecimal fromNumber) {
BigDecimal potentialBalancedNumber = fromNumber.add(BigDecimal.ONE);
while (true) {
int evenDivider = 0;
int oddDivider = 1; //to not start from 1 as divisor, it's always odd and divide potentialBalancedNumber so can start checking divisors from 2
if (isEven(potentialBalancedNumber)) {
evenDivider = 1;
} else {
oddDivider++;
}
for (BigDecimal divider = TWO; (divider.compareTo(potentialBalancedNumber.divide(TWO)) == -1 || divider.compareTo(potentialBalancedNumber.divide(TWO)) == 0); divider = divider.add(BigDecimal.ONE)) {
boolean isDivisor = potentialBalancedNumber.remainder(divider).compareTo(BigDecimal.ZERO) == 0;
if(isDivisor){
boolean isEven = divider.remainder(new BigDecimal("2")).compareTo(BigDecimal.ZERO) == 0;
boolean isOdd = divider.remainder(new BigDecimal("2")).compareTo(BigDecimal.ZERO) != 0;
if (isDivisor && isEven) {
evenDivider++;
} else if (isDivisor && isOdd) {
oddDivider++;
}
}
}
if (oddDivider == evenDivider) { //found balanced number
System.out.println(potentialBalancedNumber);
break;
}
potentialBalancedNumber = potentialBalancedNumber.add(BigDecimal.ONE);
}
}
}
It seems to work fine but is too slow. Can you please help to find way to optimize it, am I missing something?
As #MarkDickinson suggested, answer is:
private static void findBalancedNumberOptimized(BigDecimal fromNumber) { //2,6,10,14,18,22,26...
if(fromNumber.compareTo(BigDecimal.ONE) == 0){
System.out.println(2);
}
else {
BigDecimal result = fromNumber.divide(new BigDecimal("4")).setScale(0, RoundingMode.HALF_UP).add(BigDecimal.ONE);
result = (TWO.multiply(result).subtract(BigDecimal.ONE)).multiply(TWO); //2(2n-1)
System.out.println(result);
}
}
and it's finally green, thanks Mark!

Why is my recursive memoized Fibonacci code wrong?

Something in the main function is wrong, but I don't know what. If I go through the code with a debugger I can see that my code isn't even reaching the fibonacci function right now.
public class Fibonacci {
public static void main(String[] args) {
for (int n=1; n<50; n++) {
System.out.println("Element "+ n + " of the sequence: " + newFib(n));
}
}
public static ArrayList<BigInteger> memo = new ArrayList<BigInteger>();
static BigInteger newFib(int n){
assert n >= 1: "the fibonacci sequence starts at 1";
BigInteger result=BigInteger.valueOf(1);
if (memo.get(n) != null) {
return memo.get(n);
}
else if( n == 1 || n == 2 ) {
memo.add(n, BigInteger.valueOf(1));
return BigInteger.valueOf(1);
}
else {
result= newFib(n-1).add(newFib(n-2));
memo.add(n,result);
return result;
}
}
}
Your code was throwing some exceptions. You simply needed to debug the exceptions and implement the proper checks. Using the code with these changes should work as intended:
import java.math.*;
import java.util.ArrayList;
public class Fibonacci {
public static void main(String[] args) {
for (int n=1; n<50; n++) {
System.out.println("Element "+ n + " of the sequence: " + newFib(n));
}
}
public static ArrayList<BigInteger> memo = new ArrayList<BigInteger>();
static BigInteger newFib(int n){
assert n >= 1: "the fibonacci sequence starts at 1";
BigInteger result=BigInteger.valueOf(1);
if (memo.size() - 1 >= n && memo.get(n) != null) {
return memo.get(n);
}
else if( n == 1 || n == 2 ) {
memo.add(n-1, BigInteger.valueOf(1));
return BigInteger.valueOf(1);
}
else {
result= newFib(n-1).add(newFib(n-2));
memo.add(n,result);
return result;
}
}
}
Your current code does not handle out of bounds correctly and as I mentioned in the comments, the fibonacci sequence does not necessarily start at one and the logic can be simplified. I would use a HashMap<Integer, BigInteger> for storing the memoization and I would also prefer to populate the initial constants once (and as constants). For example,
private static Map<Integer, BigInteger> memo = new HashMap<>();
static {
memo.put(0, BigInteger.ZERO);
memo.put(1, BigInteger.ONE);
}
static BigInteger newFib(int n) {
if (!memo.containsKey(n)) {
if (n < 0) {
memo.put(n, newFib(n + 2).subtract(newFib(n + 1)));
} else {
memo.put(n, newFib(n - 2).add(newFib(n - 1)));
}
}
return memo.get(n);
}
Which can then be tested like
public static void main(String[] args) {
for (int i = -8; i < 9; i++) {
if (i != -8) {
System.out.print(" ");
}
System.out.printf("%-5s", String.format("F(%d)", i));
}
System.out.println();
for (int i = -8; i < 9; i++) {
if (i != -8) {
System.out.print(" ");
}
System.out.printf("%-5s", newFib(i));
}
}
To reproduce the example given in the Fibonacci number Wikipedia entry.
F(-8) F(-7) F(-6) F(-5) F(-4) F(-3) F(-2) F(-1) F(0) F(1) F(2) F(3) F(4) F(5) F(6) F(7) F(8)
-21 13 -8 5 -3 2 -1 1 0 1 1 2 3 5 8 13 21

(Arraylist) Crashes when user defined String input

The purpose of the program is to let the user input 5 numbers and select which game they would like to compare them to (lotto/lottoplus1/lottoplus2) with each having a unique set of 5 numbers, then to be stored in an arraylist.
The national lottery run three draws on each night: Lotto, Lotto plus one and Lotto plus 2.
generate numbers for each of these draws.
When a user enters a line of numbers they should also enter either:"lotto", "plus1", or "plus2" to specify which of the draws their numbers should be compared to.
This value should then be assigned to that specific line of numbers and the numbers on that line should be compared against each set of Lotto numbers as required.
Heres my problem! When I input my five numbers then lets say 'plus1' to assign the comparison of those numbers to lotteryPlusOne it crashes and outputs this message:
Exception in thread "main" java.lang.NullPointerException at lottoapp.lottoCounter.compareNums(lottoCounter.java:136) at lottoapp.LottoApp.main(LottoApp.java:61) C:\Users\x15587907\AppData\Local\NetBeans\Cache\8.1\executor‌​-snippets\run.xml:53‌​: Java returned: 1 BUILD FAILED (total time: 15 seconds)
Below is line 136 it is in the Instantiable class in the public void compareNums() method
l = madeUpArrayList.get(i); <-----
Main App
package lottoapp;
import javax.swing.JOptionPane;
import java.util.ArrayList;
import java.util.Arrays;
public class LottoApp {
public static void main(String[] args) {
//declare vars/objects/arrays
int[] lottery = new int[5]; //5 Winning numbers
int[] lotteryPlus1 = new int[5]; //5 Winning LP1 numbers
int[] lotteryPlus2 = new int[5]; //5 Winning LP2 numbers
String gameType;
int number1;
int number2;
int number3;
int number4;
int number5;
//array list called madeUpArrayList
ArrayList<lottoCounter> madeUpArrayList = new ArrayList();
//object declare and create
lottoCounter myCount = new lottoCounter();
//winNums/getLottery need to be initialised at top of program
myCount.winNums();
lottery = myCount.getLottery();
lotteryPlus1 = myCount.getLotteryPlus1();
lotteryPlus2 = myCount.getLotteryPlus2();
//Displays winning numbers (Testing Purposes)
System.out.println(Arrays.toString(lottery));
System.out.println(Arrays.toString(lotteryPlus1));
System.out.println(Arrays.toString(lotteryPlus2));
//Array List
for (int i = 0; i < 1; i++) {
lottoCounter l = new lottoCounter();
number1 = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter number 1 "));
number2 = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter number 2 "));
number3 = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter number 3 "));
number4 = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter number 4 "));
number5 = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter number 5 "));
gameType = JOptionPane.showInputDialog(null, "Select a game type for comparison ... lotto/plus1/plus2");
l.setNumber1(number1);
l.setNumber2(number2);
l.setNumber3(number3);
l.setNumber4(number4);
l.setNumber5(number5);
l.setGameType(gameType);
madeUpArrayList.add(l);
}
//Comparison
myCount.compareNums();
//Output Lotto,Lotto Plus One and Lotto plus Two correct guesses
JOptionPane.showMessageDialog(null, "Guesses correct for Regular Lottery correct is " + myCount.getCorrectLotto());
JOptionPane.showMessageDialog(null, "Guesses correct for Lottery Plus One is " + myCount.getCorrectPlusOne());
JOptionPane.showMessageDialog(null, "Guesses correct for Lottery Plus Two is " + myCount.getCorrectPlusTwo());
}
}
Instantiable Class
package lottoapp;
import java.util.ArrayList;
public class lottoCounter {
//Variables/Constants/data members
private int correctLotto;
private int correctPlusOne;
private int correctPlusTwo;
private int[] lottery = new int[5];
private int[] lotteryPlus1 = new int[5];
private int[] lotteryPlus2 = new int[5];
private int number1;
private int number2;
private int number3;
private int number4;
private int number5;
private String gameType;
private ArrayList<lottoCounter> madeUpArrayList;
//Constructor
lottoCounter() {
correctLotto = 0;
correctPlusOne = 0;
correctPlusTwo = 0;
number1 = 0;
number2 = 0;
number3 = 0;
number4 = 0;
number5 = 0;
gameType = " ";
}
//setters
public void setCorrectLotto(int correctLotto) {
this.correctLotto = correctLotto;
}
public void setCorrectPlusOne(int correctPlusOne) {
this.correctPlusOne = correctPlusOne;
}
public void setCorrectPlusTwo(int correctPlusTwo) {
this.correctPlusTwo = correctPlusTwo;
}
public void setLottery(int[] lottery) {
this.lottery = lottery;
}
public void setLotteryPlus1(int[] lotteryPlus1) {
this.lotteryPlus1 = lotteryPlus1;
}
public void setLotteryPlus2(int[] lotteryPlus2) {
this.lotteryPlus1 = lotteryPlus2;
}
public void setNumber1(int number1) {
this.number1 = number1;
}
public void setNumber2(int number2) {
this.number2 = number2;
}
public void setNumber3(int number3) {
this.number3 = number3;
}
public void setNumber4(int number4) {
this.number4 = number4;
}
public void setNumber5(int number5) {
this.number5 = number5;
}
public void setGameType(String gameType) {
this.gameType = gameType;
}
public lottoCounter(ArrayList<lottoCounter> madeUpArrayList) {
this.madeUpArrayList = madeUpArrayList;
}
//COMPUTE
//Lottery Generator | random num generator (1-40)Lottery
public void winNums() {
for (int i = 0; i < lottery.length; i++) {//Generating 1 to 40 numbers
lottery[i] = (int) Math.floor(1 + Math.random() * 40);//Using Math.random
for (int j = 0; j < i; j++) {
if (lottery[i] == lottery[j]) {
i--;
}
}
}
//Lottery plus 1 generator
for (int i = 0; i < lotteryPlus1.length; i++) {//Generating 1 to 40 numbers
lotteryPlus1[i] = (int) Math.floor(1 + Math.random() * 40);//Using Math.random
for (int j = 0; j < i; j++) {
if (lotteryPlus1[i] == lotteryPlus1[j]) {
i--;
}
}
}
//Lottery plus 2 generator
for (int i = 0; i < lotteryPlus2.length; i++) {//Generating 1 to 40 numbers
lotteryPlus2[i] = (int) Math.floor(1 + Math.random() * 40);//Using Math.random
for (int j = 0; j < i; j++) {
if (lotteryPlus2[i] == lotteryPlus2[j]) {
i--;
}
}
}
}
//Counter for Lottery/LotteryPlusOne/LotteryPlusTwo (COMPARISON)
public void compareNums() {
for (int i = 0; i < 1; i++) {
for (int j = 0; j < 5; j++) {
lottoCounter l;
l = madeUpArrayList.get(i);
if (l.getGameType().equals("lotto")) {
if (lottery[j] == l.getNumber1() || lottery[j] == l.getNumber2() || lottery[j] == l.getNumber3() || lottery[j] == l.getNumber4() || lottery[j] == l.getNumber5()) {
correctLotto++;
}
}
if (l.getGameType().equals("plus1")) {
if (lotteryPlus1[j] == l.getNumber1() || lotteryPlus1[j] == l.getNumber2() || lotteryPlus1[j] == l.getNumber3() || lotteryPlus1[j] == l.getNumber4() || lotteryPlus1[j] == l.getNumber5()) {
correctPlusOne++;
}
}
if (l.getGameType().equals("plus2")) {
if (lotteryPlus2[j] == l.getNumber1() || lotteryPlus2[j] == l.getNumber2() || lotteryPlus2[j] == l.getNumber3() || lotteryPlus2[j] == l.getNumber4() || lotteryPlus2[j] == l.getNumber5()) {
correctPlusTwo++;
}
}
}
}
}
//getters (return values to App Class)
public int getCorrectLotto() {
return correctLotto;
}
public int getCorrectPlusOne() {
return correctPlusOne;
}
public int getCorrectPlusTwo() {
return correctPlusTwo;
}
public int[] getLottery() {
return lottery;
}
public int[] getLotteryPlus1() {
return lotteryPlus1;
}
public int[] getLotteryPlus2() {
return lotteryPlus2;
}
public int getNumber1() {
return number1;
}
public int getNumber2() {
return number2;
}
public int getNumber3() {
return number3;
}
public int getNumber4() {
return number4;
}
public int getNumber5() {
return number5;
}
public String getGameType() {
return gameType;
}
public ArrayList<lottoCounter> getMadeUpArrayList() {
return madeUpArrayList;
}
}
I am not sure about anyone else but it would be nice to have more info, like the data in the arrays: lottery, lotteryPlus1 and madeUpArrayList ect. Just to make sure that they actually have any data in them because according to your Exception you have a java.lang.NullPointerException in your method compareNums in line 136 of your class. Because you did not post line numbers I am not sure when the exception occurs.
I am assuming one of your arrays does not have any data in it or one or more of your arrays do not have 5 total entries of data in it because your for loop iterates 5 times. But again without seeing how or when your arrays are instantiated I do not think it is possible for anyone to confirm that is the cause of your problems. For example lotteryPlus2[] may only have data for lotteryPlus2[0],lotteryPlus2[1],and lotteryPlus2[2] so when j gets to 3 in the loop lotteryPlus2[3] does not exist and throws a java.lang.NullPointerException.
Also I am curious on why you use this for loop for (int i = 0; i < 1; i++){}
This loop only loops once no matter what so why have it there at all since your main method will always run at least once anyways? Honest question, I am a beginner programmer so you may be using it for something that I have no knowledge about.

Create with recursion basic mathematical operations with predefined definitions

I plan in JavaFX a new Game 'Number-Shape-System'. Basically its a little memory game where pictures are associated with numbers. So '2'='Swan', '5'='Hand(Fingers)' and so on. So the player see the exercise 'Swan + Fingers = ?'.
What I want is all possible mathematically operations following rules:
/*
* Generate all possible mathematical operations to the console with the numbers
* 0-12, where every result is (>= 0 && <= 12).
* - Mathematical operations are '+', '-', '*' and '/'.
* - The rule 'dot before line' shouldn't be used, instead the operations will
* be executed from left to right.
* - Every among result must be between (>= 0 && <= 12) and a whole number.
* - Only different numbers are allowed for the operations (an operation have
* 2 numbers). For example 2+3 is allowed, 3*3 not.
*
* A solution with recursive methods would be preferred. I want the output for
* the length 2-10.
*
* Example output with different length:
* - Length 3: 2+3(=5)*2(=10)
* - Length 5: 2+3(=5)*2(=10)+2(=12)/4(=3)
*/
I have prepared a example implementation, but I don't know how to convert it to a recursive functionality.
import java.util.ArrayList;
import java.util.List;
public class Generator {
private static final List<Double> numbers = new ArrayList<>();
private static final List<String> operations = new ArrayList<>();
static {
numbers.add(0.0);
numbers.add(1.0);
numbers.add(2.0);
numbers.add(3.0);
numbers.add(4.0);
numbers.add(5.0);
numbers.add(6.0);
numbers.add(7.0);
numbers.add(8.0);
numbers.add(9.0);
numbers.add(10.0);
numbers.add(11.0);
numbers.add(12.0);
operations.add("+");
operations.add("-");
operations.add("*");
operations.add("/");
}
private int lineCounter = 0;
public Generator() {
this.init();
}
private void init() {
}
public void generate() {
// Length 2 ###########################################################
boolean okay = false;
int lineCounter = 0;
StringBuilder sbDouble = new StringBuilder();
for (Double first : numbers) {
for (Double second : numbers) {
for (String operation : operations) {
if (first == second) {
continue;
}
if (operation.equals("/") && (first == 0.0 || second == 0.0)) {
continue;
}
double result = perform(first, operation, second);
okay = this.check(result, operation);
if (okay) {
++lineCounter;
sbDouble = new StringBuilder();
this.computeResultAsString(sbDouble, first, operation, second, result);
System.out.println(sbDouble.toString());
}
}
}
}
System.out.println("Compute with length 2: " + lineCounter + " lines");
// Length 2 ###########################################################
// Length 3 ###########################################################
okay = false;
lineCounter = 0;
sbDouble = new StringBuilder();
for (Double first : numbers) {
for (Double second : numbers) {
for (String operation1 : operations) {
if (first == second) {
continue;
}
if (operation1.equals("/") && (first == 0.0 || second == 0.0)) {
continue;
}
double result1 = perform(first, operation1, second);
okay = this.check(result1, operation1);
if (okay) {
for (Double third : numbers) {
for (String operation2 : operations) {
if (second == third) {
continue;
}
if (operation2.equals("/") && third == 0.0) {
continue;
}
double result2 = perform(result1, operation2, third);
okay = this.check(result2, operation2);
if (okay) {
++lineCounter;
sbDouble = new StringBuilder();
this.computeResultAsString(sbDouble, first, operation1, second, result1);
this.computeResultAsString(sbDouble, operation2, third, result2);
System.out.println(sbDouble.toString());
}
}
}
}
}
}
}
System.out.println("Compute with length 3: " + lineCounter + " lines");
// Length 3 ###########################################################
// Length 4 ###########################################################
okay = false;
lineCounter = 0;
sbDouble = new StringBuilder();
for (Double first : numbers) {
for (Double second : numbers) {
for (String operation1 : operations) {
if (first == second) {
continue;
}
if (operation1.equals("/") && (first == 0.0 || second == 0.0)) {
continue;
}
double result1 = perform(first, operation1, second);
okay = this.check(result1, operation1);
if (okay) {
for (Double third : numbers) {
for (String operation2 : operations) {
if (second == third) {
continue;
}
if (operation2.equals("/") && third == 0.0) {
continue;
}
double result2 = perform(result1, operation2, third);
okay = this.check(result2, operation2);
if (okay) {
for (Double forth : numbers) {
for (String operation3 : operations) {
if (third == forth) {
continue;
}
if (operation3.equals("/") && forth == 0.0) {
continue;
}
double result3 = perform(result2, operation3, forth);
okay = this.check(result3, operation3);
if (okay) {
++lineCounter;
sbDouble = new StringBuilder();
this.computeResultAsString(sbDouble, first, operation1, second, result1);
this.computeResultAsString(sbDouble, operation2, third, result2);
this.computeResultAsString(sbDouble, operation3, forth, result3);
System.out.println(sbDouble.toString());
}
}
}
}
}
}
}
}
}
}
System.out.println("Compute with length 4: " + lineCounter + " lines");
// Length 4 ###########################################################
}
private boolean check(double result, String operation) {
switch (operation) {
case "+":
case "-":
case "*": {
if (result > 0 && result <= 12) {
return true;
}
break;
}
case "/": {
if (
(Math.floor(result) == result)
&& (result >= 0 && result <= 12)
) {
return true;
}
break;
}
}
return false;
}
private double perform(double first, String operation, double second) {
double result = 0.0;
switch (operation) {
case "+": { result = first + second; break; }
case "-": { result = first - second; break; }
case "*": { result = first * second; break; }
case "/": { result = first / second; break; }
}
return result;
}
private void computeResultAsString(StringBuilder sbDouble, String operation, double second, double result) {
sbDouble.append(operation);
sbDouble.append(second);
sbDouble.append("(=");
sbDouble.append(result);
sbDouble.append(")");
}
private void computeResultAsString(StringBuilder sbDouble, double first, String operation, double second, double result) {
sbDouble.append(first);
sbDouble.append(operation);
sbDouble.append(second);
sbDouble.append("(=");
sbDouble.append(result);
sbDouble.append(")");
}
public static void main(String[] args) {
final Generator generator = new Generator();
generator.generate();
}
}
As you can see in your own code, for each increase in "length", you have to nest another block of the same code. With a dynamic length value, you can't do that.
Therefore, you move the block of code into a method, and pass in a parameter of how many more times it has to "nest", i.e. a remainingLength. Then the method can call itself with a decreasing value of remainingLength, until you get to 0.
Here is an example, using an enum for the operator.
public static void generate(int length) {
if (length <= 0)
throw new IllegalArgumentException();
StringBuilder expr = new StringBuilder();
for (int number = 0; number <= 12; number++) {
expr.append(number);
generate(expr, number, length - 1);
expr.setLength(0);
}
}
private static void generate(StringBuilder expr, int exprTotal, int remainingLength) {
if (remainingLength == 0) {
System.out.println(expr);
return;
}
final int exprLength = expr.length();
for (int number = 0; number <= 12; number++) {
if (number != exprTotal) {
for (Operator oper : Operator.values()) {
int total = oper.method.applyAsInt(exprTotal, number);
if (total >= 0 && total <= 12) {
expr.append(oper.symbol).append(number)
.append("(=").append(total).append(")");
generate(expr, total, remainingLength - 1);
expr.setLength(exprLength);
}
}
}
}
}
private enum Operator {
PLUS ('+', Math::addExact),
MINUS ('-', Math::subtractExact),
MULTIPLY('*', Math::multiplyExact),
DIVIDE ('/', Operator::divide);
final char symbol;
final IntBinaryOperator method;
private Operator(char symbol, IntBinaryOperator method) {
this.symbol = symbol;
this.method = method;
}
private static int divide(int left, int right) {
if (right == 0 || left % right != 0)
return -1/*No exact integer value*/;
return left / right;
}
}
Be aware that the number of permutations grow fast:
1: 13
2: 253
3: 5,206
4: 113,298
5: 2,583,682
6: 61,064,003
7: 1,480,508,933

Java help! implementing a 2d array of a certain object, the object has multiple private data types and objects

I'm trying to make a 2d array of an object in java. This object in java has several private variables and methods in it, but won't work. Can someone tell me why and is there a way I can fix this?
This is the exeception I keep getting for each line of code where I try to initialize and iterate through my 2d object.
"Exception in thread "main" java.lang.NullPointerException
at wumpusworld.WumpusWorldGame.main(WumpusWorldGame.java:50)
Java Result: 1"
Here is my main class:
public class WumpusWorldGame {
class Agent {
private boolean safe;
private boolean stench;
private boolean breeze;
public Agent() {
safe = false;
stench = false;
breeze = false;
}
}
/**
* #param args
* the command line arguments
* #throws java.lang.Exception
*/
public static void main(String [] args) {
// WumpusFrame blah =new WumpusFrame();
// blah.setVisible(true);
Scanner input = new Scanner(System.in);
int agentpts = 0;
System.out.println("Welcome to Wumpus World!\n ******************************************** \n");
//ArrayList<ArrayList<WumpusWorld>> woah = new ArrayList<ArrayList<WumpusWorld>>();
for (int i = 0 ; i < 5 ; i++) {
WumpusWorldObject [] [] woah = new WumpusWorldObject [5] [5];
System.out.println( "*********************************\n Please enter the exact coordinates of the wumpus (r and c).");
int wumpusR = input.nextInt();
int wumpusC = input.nextInt();
woah[wumpusR][wumpusC].setPoints(-3000);
woah[wumpusR][wumpusC].setWumpus();
if ((wumpusR <= 5 || wumpusC <= 5) && (wumpusR >= 0 || wumpusC >= 0)) {
woah[wumpusR][wumpusC].setStench();
}
if (wumpusC != 0) {
woah[wumpusR][wumpusC - 1].getStench();
}
if (wumpusR != 0) {
woah[wumpusR - 1][wumpusC].setStench();
}
if (wumpusC != 4) {
woah[wumpusR][wumpusC + 1].setStench();
}
if (wumpusR != 4) {
woah[wumpusR + 1][wumpusC].setStench();
}
System.out.println( "**************************************\n Please enter the exact coordinates of the Gold(r and c).");
int goldR = input.nextInt();
int goldC = input.nextInt();
woah[goldR][goldC].setGold();
System.out.println("***************************************\n How many pits would you like in your wumpus world?");
int numPits = input.nextInt();
for (int k = 0 ; k < numPits ; k++) {
System.out.println("Enter the row location of the pit");
int r = input.nextInt();
System.out.println("Enter the column location of the pit");
int c = input.nextInt();
woah[r][c].setPit();
if ((r <= 4 || c <= 4) && (r >= 0 || c >= 0)) {
woah[r][c].setBreeze();
}
if (c != 0) {
woah[r][c - 1].setBreeze();
}
if (r != 0) {
woah[r - 1][c].setBreeze();
}
if (c != 4) {
woah[r][c + 1].setBreeze();
}
if (r != 4) {
woah[r + 1][c].setBreeze();
}
}
for (int x = 0 ; x < 4 ; x++) {
int j = 0;
while (j < 4) {
agentpts = agentpts + woah[x][j].getPoints();
Agent [] [] k = new Agent [4] [4];
if (woah[x][j].getWumpus() == true) {
agentpts = agentpts + woah[x][j].getPoints();
System.out.println("You just got ate by the wumpus!!! THE HORROR!! Your score is " + agentpts);
}
if (woah[x][j].getStench() == true) {
k[x][j].stench = true;
System.out.println("You smell something funny... smells like old person.");
}
if (woah[x][j].getBreeze() == true) {
k[x][j].breeze = true;
System.out.println("You hear a breeze. yeah");
}
if (woah[x][j].getPit() == true) {
agentpts = agentpts + woah[x][j].getPoints();
System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH! you dumb bith, your dead now.");
}
// if breeze or stench, if breeze and stench, if nothing, etc then move.
k[x][j].safe = true;
// if(k[i][j].isSafe()!=true){
// } else { }
}
}
}
}
}
Here is my class object that I'm trying to implement:
package wumpusworld;
/**
*
* #author Jacob
*/
public class WumpusWorldObject {
private boolean stench;
private boolean breeze;
private boolean pit;
private boolean wumpus;
private boolean gold;
private int points;
private boolean safe;
public WumpusWorldObject(){
}
public boolean getPit() {
return pit;
}
public void setPit() {
this.pit = true;
}
public boolean getWumpus() {
return wumpus;
}
public void setWumpus() {
this.wumpus = true;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
public boolean getStench() {
return stench;
}
public void setStench() {
this.stench = true;
}
public boolean getBreeze() {
return breeze;
}
public void setBreeze() {
this.breeze = true;
}
public boolean getSafe() {
return safe;
}
public void setSafe() {
this.safe = true;
}
public void setGold(){
this.gold=true;
}
}
Creating array doesn't mean it will be automatically filled with new instances of your class. There are many reasons for that, like
which constructor should be used
what data should be passed to this constructor.
This kind of decisions shouldn't be made by compiler, but by programmer, so you need to invoke constructor explicitly.
After creating array iterate over it and fill it with new instances of your class.
for (int i=0; i<yourArray.length; i++)
for (int j=0; j<yourArray[i].length; j++)
yourArray[i][j] = new ...//here you should use constructor
AClass[][] obj = new AClass[50][50];
is not enough, you have to create instances of them like
obj[i][j] = new AClass(...);
In your code the line
woah[wumpusR][wumpusC].setPoints(-3000);
must be after
woah[wumpusR][wumpusC] = new WumpusWorldObject();
.

Categories