Setting Parameters for Random String from Array: Exception n <= 0 - java

Edit: I am trying to pass the values of wG1...wG5, which are in the Main class, to rarityType(), which is expecting five parameters. I want these passed parameters to be used in int[], which defines the weight of the items in the rare[].
Hard-coding the values into the function (line 3) works as intended:
public String rarityType() {
String rare[] = {"Common", "Uncommon", "Rare", "Epic", "Legendary"};
int[] a = {64, 32, 24, 4, 1};
int sum = 0;
for (int i : a)
sum += i;
int s = r.nextInt(sum);
int prev_value = 0;
int current_max_value;
int found_index = -1;
for (int i = 0; i < a.length; i++) {
current_max_value = prev_value + a[i];
boolean found = (s >= prev_value && s < current_max_value);
if (found) {
found_index = i;
break;
}
prev_value = current_max_value;
}
rarityType() is not instanced in Main, it's value is retrieved via getter:
Weapon weapon = new Weapon();
String weaponRarity = weapon.getWeaponRarity();
And in the class:
private String weaponRarity = rarityType();
But I want to be able to modify those values from Main.
.
I am trying to set parameters in Main for a class that returns a weighted random string. When I have the parameters hard coded in the class, it works as expected.
The exception is telling me that the random generator returned null because it was not passed any parameters. I tried to create setters in the class and define them in Main, to no avail. My question is, how can I pass parameters to the function in the class that I instantiate in Main? Thank you for any guidance!
Note: I cannot have a constructor for this class in Main because their are other functions in the class that rely on the returned string from this function.
Main code snippet:
Weapon weapon = new Weapon();
weapon.wG1 = 1;
weapon.wG2 = 1;
weapon.wG3 = 1;
weapon.wG4 = 1;
weapon.wG5 = 1000;
Class code snippet:
public class Weapon {
public int wG1,wG2,wG3,wG4,wG5;
private Random r = new Random();
private String weaponRarity = rarityType(wG1,wG2,wG3,wG4,wG5);
public String rarityType(int w1, int w2, int w3, int w4, int w5) {
String rare[] = {"Common", "Uncommon", "Rare", "Epic", "Legendary"};
int[] a = {w1, w2, w3, w4, w5};
int sum = 0;
for (int i : a)
sum += i;
int s = r.nextInt(sum); //line 100
int prev_value = 0;
int current_max_value;
int found_index = -1;
for (int i = 0; i < a.length; i++) {
current_max_value = prev_value + a[i];
boolean found = (s >= prev_value && s < current_max_value);
if (found) {
found_index = i;
break;
}
prev_value = current_max_value;
}
String selection = "unknown";
if (found_index != -1) {
selection = rare[found_index];
}
return selection;
}
This version of the code throws an exception:
Caused by: java.lang.IllegalArgumentException: n <= 0: 0 at
net.zingrook.mobiloot.Weapon.rarityType(Weapon.java:100)

I think it happens because rarityType method is executed when you create weapon object but wG1,wG2,wG3,wG4,wG5 are not instantiated yet:
Weapon weapon = new Weapon();
probably it will make sense to create a constructor with all these parameters. Please let me know if you have any questions.

Related

How to protect arrays from changing?

I'm trying to get data from arrays that were used in method fifo and lifo. I have main array that fills from input by user. These array is used in methods fifo and lifo, the problem is that these two functions giving the same priceOfGoods, because while fifo using main array in process it changing data inside it. I want to prevent changing data in ```main array** and use it in two methods without changing data inside main array. Any ideas? Thanks!
public class Solution {
public static int[][] takingGoodsAndPrice(Scanner input, Integer m) {
final int[][] goodsAndPrice = new int[m][2];
// Taking goods and its price
for (int i = 0; i < m; i++) {
for (int j = 0; j < 2; j++) {
goodsAndPrice[i][j] = Integer.parseInt(input.next());
}
}
return goodsAndPrice;
}
public static int[] takingAmountOfSales(Scanner input, Integer k) {
final int[] amountOfSales = new int[k];
// Taking sale of goods
for (int i = 0; i < k; i++) {
amountOfSales[i] = Integer.parseInt(input.next());
}
return amountOfSales;
}
public static Integer fifo(Integer k, Integer m, int[][] goodsAndPrice, int[] amountOfSales) {
int priceOfRestGoods = 0;
int[][] goods = goodsAndPrice;
int[] amount = amountOfSales;
// Evaluates amount of goods that were not sold
for (int i = 0; i < k; i++) {
for (int j = 0; j < m; j++) {
if (amount[i] == 0)
break;
if (goods[j][0] > amount[i]) {
goods[j][0] = goods[j][0] - amount[i];
amount[i] = amount[i] - amount[i];
} else if (goods[j][0] <= amount[i]) {
amount[i] = amount[i] - goods[j][0];
goods[j][0] = 0;
}
}
}
// Evaluates price of goods that were not sold
for (int i = 0; i < m; i++) {
priceOfRestGoods = priceOfRestGoods + (goods[i][0] * goods[i][1]);
}
return priceOfRestGoods;
}
public static Integer lifo(Integer k, Integer m, int[][] goodsAndPrice, int[] amountOfSales) {
int priceOfRestGoods = 0;
// Evaluates amount of goods that were not sold
for (int i = 0; i < k; i++) {
for (int j = m-1; j >= 0; j--) {
if (amountOfSales[i] == 0)
break;
if (goodsAndPrice[j][0] > amountOfSales[i]) {
goodsAndPrice[j][0] = goodsAndPrice[j][0] - amountOfSales[i];
amountOfSales[i] = amountOfSales[i] - amountOfSales[i];
} else if (goodsAndPrice[j][0] <= amountOfSales[i]) {
amountOfSales[i] = amountOfSales[i] - goodsAndPrice[j][0];
goodsAndPrice[j][0] = 0;
}
}
}
// Evaluates price of goods that were not sold
for (int i = 0; i < m; i++) {
priceOfRestGoods = priceOfRestGoods + (goodsAndPrice[i][0] * goodsAndPrice[i][1]);
}
return priceOfRestGoods;
}
//
// public static Integer medium() {
//
// }
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
final int n = input.nextInt(); // n - total amount of goods
final int m = input.nextInt(); // m - total amount of goods that has been received
final int k = input.nextInt(); // k - total amount of goods that has been released
final int[][] goodsAndPrice = takingGoodsAndPrice(input, m);
final int[] amountOfSales = takingAmountOfSales(input, k);
System.out.println(fifo(k, m, goodsAndPrice, amountOfSales));
System.out.println(lifo(k, m, goodsAndPrice, amountOfSales));
}
}
At the moment, you're creating new variables to store the arrays, but they will reference the same array done like this, meaning that any changes made to them will also be present in the original parameters. You'll want to store a copy of the arrays in those variables instead. See here.
When you do the following
int[][] goods = goodsAndPrice;
you are still referencing the values referenced by goodsAndPrice i.e. both goods and goodsAndPrice will reference the same values. Therefore, any changes made using one of these references will be same for the other reference.
What you need to do is to create a copy of goodsAndPrice[][] and make changes to the copy. You can do create a copy of goodsAndPrice[][] as follows:
int[][] goods = Arrays.stream(goodsAndPrice).map(int[]::clone).toArray(int[][]::new);

Algorithms, 4th Edition: do not understand an example about aliasing/reference

Counter c1 = new Counter("ones");
c1.increment();
Counter c2 = c1;
c2.increment();
StdOut.println(c1);
class code link: https://introcs.cs.princeton.edu/java/33design/Counter.java
public class Counter implements Comparable<Counter> {
private final String name; // counter name
private final int maxCount; // maximum value
private int count; // current value
// create a new counter with the given parameters
public Counter(String id, int max) {
name = id;
maxCount = max;
count = 0;
}
// increment the counter by 1
public void increment() {
if (count < maxCount) count++;
}
// return the current count
public int value() {
return count;
}
// return a string representation of this counter
public String toString() {
return name + ": " + count;
}
// compare two Counter objects based on their count
public int compareTo(Counter that) {
if (this.count < that.count) return -1;
else if (this.count > that.count) return +1;
else return 0;
}
// test client
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
int trials = Integer.parseInt(args[1]);
// create n counters
Counter[] hits = new Counter[n];
for (int i = 0; i < n; i++) {
hits[i] = new Counter(i + "", trials);
}
// increment trials counters at random
for (int t = 0; t < trials; t++) {
int index = StdRandom.uniform(n);
hits[index].increment();
}
// print results
for (int i = 0; i < n; i++) {
StdOut.println(hits[i]);
}
}
}
The book says it will print "2ones", and the process is shown in the picture above.
But I can't get it. In my opinion, c1 adds so its object adds, so we get "2";then copy c1 to c2, c2 gets "2" as well. As c2 adds, the object will turn to the unknown next grid.
When printing c1, I think we should get "2" rather than "2ones". So what's wrong with my process?
Thanks in advance.
Counter c1 = new Counter("ones");
c1.increment();
Counter c2 = c1;
c2.increment();
StdOut.println(c1);
I think this demonstration should just show Referencing.
Since you are creating just 1 object of type counter.
And assigning the value of c1, to the variable (Counter) c2 and then use the method .increment() on the variable c2 , c1 will change .
Since c2 and c1 are both referencing to the same object in memory .
So changes to c1 and c2 will both affect the same object.

error ';' expected in array defining, ; already used

public class AssignmentChapter8
{
public static void main(String[] args)
{
int randomNumbers = new int[100];
int counter = 0;
while(counter < randomNumbers.length)
{
randomNumbers[counter] = (int)(Math.random() * 25);
counter++;
}
int oddNumbers[] = new int[100];
oddNumbers[] = getOddNumbers(randomNumbers);
int evenNumbers[] = new int[100];
evenNumbers[] = getEvenNumbers(randomNumbers);
System.out.println("The odd numbers are:");
for(int k = 0; k < oddNumbers.length; k++)
System.out.print("\t" + oddNumbers[k]);
System.out.println("The even numbers are:");
for(int l = 0; l < evenNumbers.length; l++)
System.out.print("\t" + evenNumbers[l]);
}
public static int getOddNumbers(int randomNumbers)
{
int oddNumbers[] = new int[100];
int counterA = 0;
int counterB = 0;
int counter = 0;
int placeholder;
while(counter < randomNumbers.length)
{
if(randomNumbers[counterA] % 2 > 0)
{
oddNumbers[counterB] = randomNumbers[counterA];
counterB++;
}
counterA++;
counter++;
}
return oddNumbers;
}
public static int getEvenNumbers(int randomNumbers)
{
int evenNumbers[] = new int[100];
int counterA = 0;
int counterB = 0;
int counter = 0;
int placeholder;
while(counter < randomNumbers.length)
{
if(randomNumbers[counterA] % 2 > 0)
{
evenNumbers[counterB] = randomNumbers[counterA];
counterB++;
}
counterA++;
counter++;
}
return evenNumbers;
}
}
I have been trying to execute a program to sort variables in arrays, but I keep getting a ';' expected error in the line after declaration of the array where the program is supposed to retrieve an array from a function. Any help would be appreciated.
This is bad syntax (which causes the ';' expected error ):
oddNumbers[] = getOddNumbers(randomNumbers);
The brackets are not needed. You can do this:
oddNumbers = getOddNumbers(randomNumbers);
Besides that, you have plenty of errors:
int randomNumbers[] = new int[100]; // you need the brackets
Your return value in the method declaration is wrong (you are returning an array, not an int):
public static int[] getEvenNumbers(int randomNumbers)
int oddNumbers[] = new int[100];
By initializing oddNumbers become an array. when you want to assign values,
oddNumbers={elements of array}
Both left and right hand side both should arrays.
May be you should use IDE for coding then it may help you to understand some issues like this.

converting a matrix to string

I am working on writing a matrix, but unfortunately I am stuck with the output.
Instead of showing a matrix, it shows me something like:
actual matrix is
Matrix#512fb063
I need to convert the matrix to a string so that the output will look like this:
expected the matrix:
3 8 72
4 6 60
253 2 1
the code that I've written is this:
import java.util.Random;
final public class Matrix {
private final int size1; // number of rows
private final int size2; // number of columns
private final int[][] data; // M-by-N array
// create size1-by-size2 matrix of 0's
public Matrix(int size1, int size2) {
this.size1 = size1;
this.size2 = size2;
data = new int[size1][size2];
}
// create matrix based on 2d array
public Matrix(int[][] data) {
size1 = data.length;
size2 = data[0].length;
this.data = new int[size1][size2];
for (int i = 0; i < size1; i++)
for (int j = 0; j < size2; j++)
this.data[i][j] = data[i][j];
}
// creates and returns a random size1-by-size1 matrix with values between 0 and 255
public String toString(int size1, int size2) {
Matrix A = new Matrix(size1, size2);
String str = " ";
final int white = 0;
final int black = 255;
for (int i = 0; i < size1; i++)
for (int j = 0; j < size2; j++)
{
A.data[i][j] = white + (int)(Math.random() * ((black ) ));
str = (A.data[i][j]+"\t"+A.data[i][j+1]);
if (i==size1 &&j==size2) str = (A.data[i][j]+"\n");
}
return str;
}
You need to override the public String toString() function. What you are doing now is creating a new function called String toString(int size1, int size2).
Your new function is not called when writing:
System.out.println(myMatrix);
You could either do:
System.out.println(myMatrix.toString(2, 2));
or override the default toString() function.
So the following code should work:
#Override
public String toString() {
Matrix A = new Matrix(size1, size2);
String str = " ";
final int white = 0;
final int black = 255;
for (int i = 0; i < size1; i++)
for (int j = 0; j < size2; j++)
{
A.data[i][j] = white + (int)(Math.random() * ((black ) ));
str = (A.data[i][j]+"\t"+A.data[i][j+1]);
if (i==size1 &&j==size2) str = (A.data[i][j]+"\n");
}
return str;
}
where size1 and size2 are variables in the class.
Your output of actual matrix is Matrix#512fb063 is actually the memory address in Java that your instance of the class Matrix sits in. That's because your program doesn't know how to "print" this class - it doesn't magically know that you want a row/column representation of it.
You've got a number of options:
Your toString(int size1, int size2) is perfect. So when you want to print your matrix, you can go System.out.println(someMatrix.toString(2,2)) will work where someMatrix is an instance of your Matrix class.
If you want it to work properly by you just going System.out.println(someMatrix) then you will need to overwrite your Matrix class' toString() function. You -almost- did that in your toString(int size1, int size2) function but it didn't work because it needs to match exactly the parameters, ie: toString() should take 0 parameters. You will need to write a toString() method which can then call your toString(int size1, int size2)
Somehow you get the hashcode. Maybe you can use http://math.nist.gov/javanumerics/jama/doc/ matrix implementation.
I think this line is not working
str = (A.data[i][j]+"\t"+A.data[i][j+1]);
Don't you get an IndexOutOfBoundexception? Anyway A.data[i][j+1] is always empty within the loop. By the way, Variables in Java are always lower case.
You can simply do :
#Override
public String toString()
{
return toString(size1,size2);
}
Edit : If you want to reflect the real content of your current Matrix :
#Override
public String toString()
{
StringBuilder sbResult = new StringBuilder();
for(int i = 0; i < size1;i++)
{
for(int j = 0; j < size2;j++)
{
sbResult.append(A.data[i][j]);
sbResult.append("\t");
sbResult.append(A.data[i][j+1]);
if(i == size1 && j == size2)
{
sbResult.append("\n");
}
}
}
return sbResult.toString();
}

getting error StringIndexOutOfBoundsException: String index out of range [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am trying to build a matrix with row and column having values such as "aaa" for aligning purposes. but when I run it I get an error. below is my code
public class compute_matrix {
static String seq1="aaa";
static String seq2="aaa";
static int[][] matrix;
static int max_row;
static int max_col;
private static int match_reward=1;
private static int mismatch_penalty= -1;
private static int gap_cost= -1;
private static boolean case_sensitive;
private static boolean isCaseSensitive() {
return case_sensitive;
}
private static int max(int ins, int sub, int del, int i) {
if (ins > sub) {
if (ins > del) {
return ins > i? ins : i;
} else {
return del > i ?del : i;
}
} else if (sub > del) {
return sub> i ? sub : i;
} else {
return del > i ? del : i;
}
}
protected char sequence[];
public static void main(String args[]){
int r, c, rows, cols, ins, sub, del, max_score;
rows = seq1.length()+1;
cols = seq2.length()+1;
matrix = new int [rows][cols];
// initiate first row
for (c = 0; c < cols; c++)
matrix[0][c] = 0;
// keep track of the maximum score
max_row = max_col = max_score = 0;
// calculates the similarity matrix (row-wise)
for (r = 1; r < rows; r++)
{
// initiate first column
matrix[r][0] = 0;
for (c = 1; c < cols; c++)
{
sub = matrix[r-1][c-1] + scoreSubstitution(seq1.charAt(r),seq2.charAt(c));
ins = matrix[r][c-1] + scoreInsertion(seq2.charAt(c));
del = matrix[r-1][c] + scoreDeletion(seq1.charAt(r));
// choose the greatest
matrix[r][c] = max (ins, sub, del, 0);
if (matrix[r][c] > max_score)
{
// keep track of the maximum score
max_score = matrix[r][c];
max_row = r; max_col = c;
}
}
}
}
private static int scoreSubstitution(char a, char b) {
if (isCaseSensitive())
if (a == b)
return match_reward;
else
return mismatch_penalty;
else
if (Character.toLowerCase(a) == Character.toLowerCase(b))
return match_reward;
else
return mismatch_penalty;
}
private static int scoreInsertion(char a) {
return gap_cost;
}
private static int scoreDeletion(char a) {
return gap_cost;
}
public char charAt (int pos)
{
// convert from one-based to zero-based index
return sequence[pos-1];
}
}
and my error is displaying this
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 3
at java.lang.String.charAt(String.java:695)
at compute_matrix.main(compute_matrix.java:67)
Java Result: 1
rows = seq1.length()+1;
cols = seq2.length()+1;
matrix = new int [rows][cols];
and then later:
for (c = 1; c < cols; c++)
{
//when c == cols-1, it is also `seq2.length()`
//the access to seq2.charAt(c) will cause this exception then.
sub = matrix[r-1][c-1] + scoreSubstitution(seq1.charAt(r),seq2.charAt(c));
ins = matrix[r][c-1] + scoreInsertion(seq2.charAt(c));
del = matrix[r-1][c] + scoreDeletion(seq1.charAt(r));
In the above loop, when c == cols-1, it is also seq2.length(), the access to seq2.charAt(c) will cause this exception then.
You initialize the number of rows and cols to length() + 1, while you later iterate from 0 to length (inclusive), while the string contain only length() chars - from 0 to n exclusive.
If you are a C programmer in your past - I assume you are expecting a \0 terminator at the end of the string. In java you don't have those - since String is an object - you can hold a field to indicate its exact length. Meaning the last char in the string, is actually the last character there.
in line 60 of your code
sub = matrix[r-1][c-1] + scoreSubstitution(seq1.charAt(r),seq2.charAt(c));
max value for r is 4 so when you look up for seq.charAt(3) there is nothingso it shows index out of bound
I refactored your code into more canonical java.
The things I've changed:
The class is now called SimilarityMatrix, a more appropriate, self documenting name
variable declarations now happen where they get used as opposed to at the top of main
The work is now done in an instance of the class rather than the main method
I used the built in Math.max(int, int) instead of rolling my own
I removed a lot of unnecessary nested if statements. Java's short circuit evaluation helps here
Since both r and c as well as r+1 and c+1 are used frequently in your calculation loop, I track both
I removed many of the dependencies on static state (made many things instance variables)
Static state that remains is all final now (I made them constants)
Used more java-y variable names (java people really like their camel case)
public class SimilarityMatrix
{
public static final int matchReward = 1;
public static final int mismatchPenalty = -1;
public static final int gapCost = -1;
private int[][] matrix;
private int maxRow = 0;
private int maxCol = 0;
private boolean caseSensitive = false;
SimilarityMatrix(String s1, String s2, boolean dontIgnoreCase)
{
this(s1, s2);
caseSensitive = dontIgnoreCase;
}
SimilarityMatrix(String s1, String s2)
{
int rows = s1.length() + 1;
int cols = s2.length() + 1;
matrix = new int[rows][cols];
int max_score = 0;
for (int x = 0; x < cols; x++)
{
matrix[0][x] = 0;
matrix[x][0] = 0;
}
for (int r = 0, rp1 = 1; rp1 < rows; ++r, ++rp1)
{
for (int c = 0, cp1 = 1; cp1 < rows; ++c, ++cp1)
{
int sub = matrix[r][c] + scoreSubstitution(s1.charAt(r), s2.charAt(c));
int ins = matrix[rp1][c] + scoreInsertion(s2.charAt(c));
int del = matrix[r][cp1] + scoreDeletion(s1.charAt(r));
// choose the greatest
matrix[rp1][cp1] = Math.max(Math.max(ins, sub), Math.max(del, 0));
if (matrix[rp1][cp1] > max_score)
{
// keep track of the maximum score
max_score = matrix[rp1][cp1];
maxRow = rp1;
maxCol = cp1;
}
}
}
}
public static void main(String args[])
{
SimilarityMatrix me = new SimilarityMatrix("aaa", "aaa");
System.out.println(me.getMaxRow() + " " + me.getMaxCol());
}
private int scoreSubstitution(char a, char b)
{
if ((a == b && caseSensitive) || Character.toLowerCase(a) != Character.toLowerCase(b))
return matchReward;
else
return mismatchPenalty;
}
public int getMaxRow()
{
return maxRow;
}
public int getMaxCol()
{
return maxCol;
}
private int scoreInsertion(char a)
{
return gapCost;
}
private int scoreDeletion(char a)
{
return gapCost;
}
}

Categories