So as the title, I've got different results running my Magic Square program from Eclipse and cmd command. The eclipse one does not make sense.
(The position of sentence "Wrong number..." should be wrong in the eclipse one)
Anyone know how to fix it? Thanks a lot!
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class MagicSquare{
// the two-dimensional array to restore my own magic square.
private int[][] myMagicSquare;
private int n;
public MagicSquare(){
}
/**
* Function: this constructor takes and positive, odd integer parameter to generate a new
* magic square.</br>
* #param n the length of magic square</br>
* #throws IllegalArgumentException for negative or even parameter.
* Preston Jul 5, 20151:15:40 AM</br>
*/
public MagicSquare(int n){
//throws runtime error.
if(!rangeCheck(n)){
throw new IllegalArgumentException("Illegal number");
}else{
// create my magic square array with length of given integer.
this.n = n;
myMagicSquare = new int[n][n];
// generate the magic square.
createMagicSquare();
}
}
/**
*
* Function: this constructor takes a 2D array as a parameter. If the 2D array can generate
* a magic square, then put the values into <i>my magic square</i></br>, if not then throws
* the exception.
* #param newMagicSquare the tested 2D array</br>
* #throws IllegalArgumentException
* Preston Jul 5, 20151:23:10 AM</br>
*/
public MagicSquare(int[][] newMagicSquare){
this.n = newMagicSquare.length;
// determine whether or not the 2D array can generate a magic square.
if(isMagic(newMagicSquare))
myMagicSquare = newMagicSquare;
else
throw new IllegalArgumentException("This is not a magic square");
}
/**
*
* Function:Range check for the input of magic square length</br>
* #param n the length of magic square
* #return true if the length is a positive, odd number</br>
* Preston Jul 5, 20152:53:29 PM</br>
*/
private static boolean rangeCheck(int n){
return !((n>0&&n%2==0)||n<=0);
}
/**
*
* Function: return the magic number of the magic square.</br>
* #return the value magic number.</br>
* Preston Jul 5, 20151:29:02 AM</br>
*/
private int getMagicNumber(){
return (n*(n*n+1))/2;
}
/**
*
* Function: For challenging level: check if all numbers for 1 to n*n only appeared once
* in the given 2D array.</br>
* #param temp the temporary 2D array as parameter.
* #return true if all numbers from 1 to n*n only appeared once</br>
* Preston Jul 5, 20151:30:03 AM</br>
*/
private static boolean noRepeatedNum(int[][] temp){
int n = temp.length;
// Set up the standard Set for comparison.
Set<Integer> standardSet = new HashSet<>();
for(int i=1;i<=n*n;i++){
standardSet.add(i);
}
// the Set made of all numbers from temp. All repeated numbers show only once in Set.
Set<Integer> arraySet = new HashSet<>();
for(int[] x : temp){
for(int a : x){
arraySet.add(a);
}
}
// return if two Sets are equal.
return arraySet.equals(standardSet);
}
/**
*
* Function: Check if the given 2D array can consist a magic square</br>
* #param temp a parameter 2D array.
* #return true if numbers in the parameter array could consist a magic square</br>
* Preston Jul 5, 20151:36:44 AM</br>
*/
private static boolean isMagic(int[][] temp){
//store the return value
boolean isMagic = true;
int tempN = temp.length;
int magicNumber = (tempN*(tempN*tempN+1))/2;
// accumulator for two diagonals
int diagonalOneSum = 0;
int diagonalTwoSum = 0;
// check rows and columns
for(int i=0; i<tempN;i++){
int rowSum = 0;
int columnSum = 0;
for(int j=0;j<tempN;j++){
// single-row sum
rowSum += temp[i][j];
// single-column sum
columnSum += temp[j][i];
}
if(rowSum!=magicNumber||columnSum!=magicNumber){
isMagic = false;
// return false immediately if there's inequality. Save calculations and performance.
return isMagic;
}
}
// counter for the second diagonal
int diagonalTwoCounter = tempN-1;
// sum of two diagonals
for(int i=0;i<temp.length;i++){
diagonalOneSum += temp[i][i];
diagonalTwoSum += temp[diagonalTwoCounter][diagonalTwoCounter];
diagonalTwoCounter--;
}
if(diagonalOneSum!=magicNumber||diagonalTwoSum!=magicNumber){
isMagic = false;
return isMagic;
}
// check if there are repeated numbers in the pretty magic square already.
return noRepeatedNum(temp);
}
/**
*
* Function: check if the position of the number in the magic square is at boundary</br>
* #param boundary the row OR column number of the position
* #return true if the value of<code>boundary</code> is zero</br>
* Preston Jul 5, 20151:53:24 PM</br>
*/
private boolean Boundary(int boundary){
return boundary==0;
}
/**
*
* Function: Put numbers from 1 to n*n into my own 2D array using Siamese Method.</br>
* Preston Jul 5, 20153:20:56 PM</br>
*/
private void createMagicSquare(){
// starting Row number -> middle
int startRow = this.n/2;
// starting Column number -> the first column
int startColumn = 0;
// start to put number from 2
int startNum = 2;
// put 1 in the starting position
myMagicSquare[startRow][startColumn] = 1;
while(startNum<=n*n){
// the positions on upper boundary
if(Boundary(startRow)&&!Boundary(startColumn)){
myMagicSquare[n-1][startColumn-1] = startNum;
startRow = n-1;
startColumn -= 1;
}
// the positions on left boundary
else if(Boundary(startColumn)&&!Boundary(startRow)){
myMagicSquare[startRow-1][n-1] = startNum;
startRow -= 1;
startColumn = n-1;
}
// upper left corner.
else if(Boundary(startRow)&&Boundary(startColumn)){
myMagicSquare[startRow][startColumn+1] = startNum;
startColumn += 1;
}
else{
// if the coming position is filled with number.
if(myMagicSquare[startRow-1][startColumn-1]!=0){
myMagicSquare[startRow][startColumn+1] = startNum;
startColumn += 1;
}
// general movement
else{
myMagicSquare[startRow-1][startColumn-1] = startNum;
startRow -= 1;
startColumn -= 1;
}
}
startNum++;
}
}
public String toString() {
// align my 2D array.
return toString(myMagicSquare);
}
/**
*
* Function:align the numbers in the parameter 2D array pretty</br>
* #param temp the parameter 2D array.
* #return the beautifully aligned String</br>
* Preston Jul 5, 20153:26:15 PM</br>
*/
public static String toString(int[][] temp){
int largestNum = 0;
// get the largest number in temp.
for(int[] x : temp){
for(int a : x){
if(a>=largestNum)
largestNum = a;
}
}
// how many digits does the biggest number have?
int longestDigit = String.valueOf(largestNum*largestNum).length();
// store the final String
StringBuilder printOut = new StringBuilder();
printOut.append('\n');
for(int[] x : temp){
for(int a : x){
// space between each number
printOut.append('\t');
// add spaces for alignment.
for(int i=0;i<longestDigit-String.valueOf(a).length();i++){
printOut.append(" ");
}
printOut.append(String.valueOf(a));
}
printOut.append('\n').append('\n');
}
// return the big String
return printOut.toString();
}
/**
*
* Function: the main function scans user input as the length of 2D array to make my
* own magic square. If the <code>userInput</code> is out of range, print out the error
* message and ask for the number again. Enter the code 0 to exit.</br>
* #param args</br>
* Preston Jul 5, 20153:28:57 PM</br>
*/
public static void main(String[] args) {
int userInput;
do{
// title
System.out.println("Enter a positive, odd number");
System.out.print("Exit code is 0, enter 0 to quit: ");
// user input
userInput = new Scanner(System.in).nextInt();
// if the userInput is out of range, show error message.
if(rangeCheck(userInput)){
MagicSquare m = new MagicSquare(userInput);
System.out.println(m.toString());
}else
if(userInput==0)
System.out.println("The magic square is not generated. QUIT");
else
System.err.println("Wrong number: Please enter a positive, odd number");
// restart
System.out.println("-------------------");
}while(userInput != 0); // enter 0 to exit.
}
}
The reason for above issue is that bug in handling of stdout and stderr in eclipse.Follow this link. (Not sure whether this is fixed or not.)
I also tried to reproduce this issue, but it is occurring in some cases and in some cases output and error output is showing at correct places.
Just for check :-
You may get this issue at very first run on eclipse, so don't exit the code, try again with wrong number (i.e. 2/4/6 ...) ;you may see error and output gets correctly printed.
Related
I'm trying to print out the full array id[] after each time the union() method is called. in the main() method. also need to bee able to count the number of times the array is accessed. I am aware that it is accessed twice when calling the connected method, once when calling find() and up to 2n + 1 when calling union(). Please help.
public class QuickFindUF {
private int[] id; // id[i] = component identifier of i
private int count; // number of components
/**
* Initializes an empty union–find data structure with {#code n} sites
* {#code 0} through {#code n-1}. Each site is initially in its own
* component.
*
* #param n the number of sites
* #throws IllegalArgumentException if {#code n < 0}
*/
public QuickFindUF(int n) {
count = n;
id = new int[n];
for (int i = 0; i < n; i++)
id[i] = i;
}
/**
* Returns the number of components.
*
* #return the number of components (between {#code 1} and {#code n})
*/
public int count() {
return count;
}
/**
* Returns the component identifier for the component containing site {#code p}.
*
* #param p the integer representing one site
* #return the component identifier for the component containing site {#code p}
* #throws IndexOutOfBoundsException unless {#code 0 <= p < n}
*/
public int find(int p) {
validate(p);
return id[p];
}
// validate that p is a valid index
private void validate(int p) {
int n = id.length;
if (p < 0 || p >= n) {
throw new IndexOutOfBoundsException("index " + p + " is not between 0 and " + (n-1));
}
}
/**
* Returns true if the the two sites are in the same component.
*
* #param p the integer representing one site
* #param q the integer representing the other site
* #return {#code true} if the two sites {#code p} and {#code q} are in the same component;
* {#code false} otherwise
* #throws IndexOutOfBoundsException unless
* both {#code 0 <= p < n} and {#code 0 <= q < n}
*/
public boolean connected(int p, int q) {
validate(p);
validate(q);
return id[p] == id[q];
}
/**
* Merges the component containing site {#code p} with the
* the component containing site {#code q}.
*
* #param p the integer representing one site
* #param q the integer representing the other site
* #throws IndexOutOfBoundsException unless
* both {#code 0 <= p < n} and {#code 0 <= q < n}
*/
public void union(int p, int q) {
validate(p);
validate(q);
int pID = id[p]; // needed for correctness
int qID = id[q]; // to reduce the number of array accesses
// p and q are already in the same component
if (pID == qID)
return;
for (int i = 0; i < id.length; i++)
if (id[i] == pID) id[i] = qID;
count--;
}
/**
* Reads in a sequence of pairs of integers (between 0 and n-1) from standard input,
* where each integer represents some site;
* if the sites are in different components, merge the two components
* and print the pair to standard output.
*
* #param args the command-line arguments
*/
public static void main(String[] args) {
int n = StdIn.readInt();
QuickFindUF uf = new QuickFindUF(n);
while (!StdIn.isEmpty()) {
int p = StdIn.readInt();
int q = StdIn.readInt();
if (uf.connected(p, q)){
continue;
}
uf.union(p, q);
StdOut.println(p + " " + q);
}
StdOut.println(uf.count() + " components");
}
}
Trying to break down your question...
Part 1:
I'm trying to print out the full array id[] after each time the union
method is called. in the main method.
try to create a string buffer and add the elements while you access it. once you are done and wanna print the array, you can just print the string buffer..
public void union(int p, int q) {
validate(p);
validate(q);
int pID = id[p]; // needed for correctness
int qID = id[q]; // to reduce the number of array accesses
// p and q are already in the same component
if (pID == qID)
return;
StringBuilder sb=new StringBuilder("");
for (int i = 0; i < id.length; i++)
{
sb.append(id[i]) + " "; // you are accessing all id elements anyway; add it to the 'sb' string while you are at it
// seperate each id element with a space
// do it in this place (before the if statement below) if you would like to print the before state of the array
if (id[i] == pID)
id[i] = qID;
//sb.append(id[i]) + " "; // do it here if you would like to print the after state of the array
}
System.out.println(sb);
count--;
}
Part 2:
also need to bee able to count the number of times the array is
accessed. i am aware that it is accessed twice when calling the
connected method, once when calling find() and up to 2n + 1 when
calling union()
For this you need to consider refactoring your code.. since you are dealing with arrays in the same class, you will not be able to count the number of times you access this array.. You can however consider having the Array in a different class as a private variable. create points of access via a getter and/or setter methods. then you can count the number of times you access the array in a reliable way..
hope this helps..
This is more of a general solution for printing an array of primitives in java. You could do it much more simple than this by iterating over the array and printing each member, inserting a newline character once your print loop has completed it's last loop.
int length = Array.getLength(aObject);
Object[] objArr = new Object[length];
for (int i=0; i<length; i++)
objArr[i] = Array.get(aObject, i);
System.out.println(Arrays.toString(objArr))
Try a search next time :)
Print arrays in Java
I have to distribute i. no. of items into n no. of boxes where each box has different capacity level c1, c2 ... cn. I want to distribute the items in ratio of their capacity. So the box with highest capacity will contain highest no. of items and vice versa. The capacities may not be in ascending order. The capacities can also be 0. Also, if the no. of items exceed the total capacity, then fill all the boxes upto their maximum capacity.
Is there already a solution for this problem?
Because I've written following algo. But it's not efficient. Also its looping infinitely at following input. Since the -2 difference is never settled. So there must also be other use cases where it breaks.
int[] arrCap = {1,1,0,1,1};
new Distributor(arrCap, 2).distribute();
import java.util.Arrays;
public class Distributor {
/** Capacity of each box */
private final int[] boxCapacity;
/** Total no. of boxes */
private final int NO_OF_BOXES;
/** Total no. of items that are to be distributed into each box */
private final int NO_OF_ITEMS;
/** Total capacity available. */
private long totalCapacity;
/** Fractionally ratio distributed items according to capacity */
private float[] fractionalRatios;
/** Ratio distributed items according to capacity */
private int[] ratioDistributedCapacity;
/** Sorted Rank of distributed items in ascending / descending order */
private int[] rankIndex;
/** The difference between the totalCapacity and total of ratioDistributedCapacity */
private int difference;
/**
* Validates the total capacity and no. of items to be distributed.
* Initializes the distributor with box capacity array, no of items.
* Implicitly calculates no. of boxes as length of box capacity array.
* #param boxCapacity Array of capacity of each box.
* #param noOfItems No. of Items to be distributed.
*/
public Distributor(int[] boxCapacity, int noOfItems) {
calculateBoxes(boxCapacity);
this.boxCapacity = boxCapacity;
this.NO_OF_ITEMS = noOfItems;
NO_OF_BOXES = boxCapacity.length;
ratioDistributedCapacity = new int[NO_OF_BOXES];
rankIndex = new int[NO_OF_BOXES];
}
/**
* Calculates the ratio into which the items are to be distributed.
* Actually assigns the items into each box according to the ratio.
* #return Array of int[] containing ratio distributed items according to its capacity.
*/
public int[] distribute() {
// If NO_OF_ITEMS to be distributed is more than totalCapacity then distribute all the items upto full capacity
if (NO_OF_ITEMS >= totalCapacity) {
ratioDistributedCapacity = boxCapacity;
} else {
calculateRatioAndDistribute();
}
return ratioDistributedCapacity;
}
/**
* Calculates the ratio & distributes the items according to the capacity.
*/
private void calculateRatioAndDistribute() {
fractionalRatios = new float[NO_OF_BOXES];
for (int i=0; i<NO_OF_BOXES; i++) {
fractionalRatios[i] = ((float) boxCapacity[i] * (float) NO_OF_ITEMS) / (float) totalCapacity;
ratioDistributedCapacity[i] = Math.round(fractionalRatios[i]);
}
print(fractionalRatios);
print(ratioDistributedCapacity);
// keep redistributing the difference until its not 0
while ((difference = rectifyAndGetDistributionResult()) != 0) {
redistribute();
}
print(ratioDistributedCapacity);
}
/**
* Redistributes the difference between the already allotted ratioDistributedCapacity array.
* Also if the difference is 0 that means everything is already settled.
* No more further need to do anything.
* #param difference the difference that needs to be settled to equal the no. of items with total distributed items.
*/
private void redistribute() {
if (difference > 0) {
// calculate distribution ranks in ascending order
calculateDistributionRanks(true); // orderDescending = true
// eliminate the invalid ranks from rankIndex
eliminateInvalidRanks();
// In case all the ranks have become invalid. In this case the rankIndex will be empty.
// So we need to re calculate the distribution ranks in opposite order.
if (rankIndex.length == 0) {
calculateDistributionRanks(false); // orderDescending = false
}
} else if (difference < 0) {
// calculate distribution ranks in descending order
calculateDistributionRanks(false); // orderDescending = false
// eliminate the invalid ranks from rankIndex
eliminateInvalidRanks();
// In case all the ranks have become invalid. In this case the rankIndex will be empty.
// So we need to re calculate the distribution ranks in opposite order.
if (rankIndex.length == 0) {
calculateDistributionRanks(true); // orderDescending = true
}
}
// add / substract 1 from the ratioDistributedCapacity of the element in order of the rankIndex
// according to negative / positive difference until the difference becomes 0.
final int len = rankIndex.length;
for (int i=0; i<len; i++) {
if (difference == 0) {
break;
} else if (difference > 0) {
ratioDistributedCapacity[ rankIndex[i] ]++;
difference--;
} else if (difference < 0) {
ratioDistributedCapacity[ rankIndex[i] ]--;
difference++;
}
}
}
/**
* If the value of any ratioDistributedCapacity element exceeds its capacity or is less than 0,
* revert it with its initial capacity value.
*/
private void rectify() {
for (int i=0; i<NO_OF_BOXES; i++) {
ratioDistributedCapacity[i] = ((ratioDistributedCapacity[i] > boxCapacity[i]) || (ratioDistributedCapacity[i] < 0)) ? boxCapacity[i] : ratioDistributedCapacity[i];
}
}
/**
* Calculates the distribution ranks i.e. indexes of fractionalRatios array.
* Sorts them into ascending or descending order.
* #param orderDesc Sort order. true for descending and false for ascending.
*/
private void calculateDistributionRanks(boolean orderDesc) {
// Copy fractionalRatios array to another tmp array. Note:- Use fractionalRatios so ranking can be more accurate.
float[] tmp = Arrays.copyOf(fractionalRatios, NO_OF_BOXES);
// Sort the array in ascending order
Arrays.sort(tmp);
// re-initialize the rankIndex array
rankIndex = new int[NO_OF_BOXES];
for (int i=0; i<NO_OF_BOXES; i++) {
innerLoop: for (int j=0; j<NO_OF_BOXES; j++) {
if (tmp[i] == fractionalRatios[j]) {
// Store the array index of unsorted array if its value matches value of sorted array.
rankIndex[i] = j;
break innerLoop;
}
}
}
// reverse the rank array if orderDesc flag is true
if (orderDesc) reverse();
print(rankIndex);
}
/**
* Remove the indexes from rank which are already full or equal to 0
* or are not eligible for increment / decrement operation.
*/
private void eliminateInvalidRanks() {
final int len = rankIndex.length;
int invalidRankCount = 0;
final int markInvalidRank = -1;
for (int i = 0; i < len; i++) {
if (boxCapacity[rankIndex[i]] <= 0) {
// mark this rank number as invalid, for removal
rankIndex[i] = markInvalidRank;
invalidRankCount++;
continue;
}
if (difference > 0) {
if ((ratioDistributedCapacity[rankIndex[i]] >= boxCapacity[rankIndex[i]])) {
// mark this rank number as invalid, for removal
rankIndex[i] = markInvalidRank;
invalidRankCount++;
continue;
}
} else if (difference < 0) {
if (ratioDistributedCapacity[rankIndex[i]] <= 0) {
// mark this rank number as invalid, for removal
rankIndex[i] = markInvalidRank;
invalidRankCount++;
continue;
}
}
}
int[] tmp = new int[(len - invalidRankCount)];
int j = 0;
for (int i = 0; i < len; i++) {
if (rankIndex[i] != markInvalidRank) {
tmp[j++] = rankIndex[i];
}
}
rankIndex = tmp;
print(rankIndex);
}
/**
* Rectifies the elements value inside ratioDistributedCapacity.
* Calculates the total of already distributed items.
* #return Difference between total distributed items and initial no. of items that were to be distributed.
*/
private int rectifyAndGetDistributionResult() {
rectify();
int remaining = NO_OF_ITEMS;
for (int tmp: ratioDistributedCapacity) {
remaining -= tmp;
}
return remaining;
}
/**
* Validates the capacity array and no. of items to be distributed.
* #param arrCapacity Array of capacity of each box.
*/
private void calculateBoxes(int[] arrCapacity) {
for (int i: arrCapacity) {
totalCapacity += i;
}
}
/**
* Prints the array elements and the total of the elements within it.
* #param x
*/
private void print(int[] x) {
final int len = x.length;
final StringBuilder sb = new StringBuilder("");
for (int i=0; i<len; i++) {
sb.append(x[i]).append(", ");
}
System.out.println(sb.toString());
}
/**
* Prints the array elements and the total of the elements within it.
* #param x
*/
private void print(float[] x) {
final int len = x.length;
final StringBuilder sb = new StringBuilder("");
for (int i=0; i<len; i++) {
sb.append(x[i]).append(", ");
}
System.out.println(sb.toString());
}
private void reverse() {
final int len = rankIndex.length;
for (int i=0; i < (len/2); i++) {
rankIndex[i] += rankIndex[len - 1 - i]; // a = a+b
rankIndex[len - 1 - i] = rankIndex[i] - rankIndex[len - 1 - i]; // b = a-b
rankIndex[i] -= rankIndex[len - 1 - i]; // a = a-b
}
}
}
I wonder if you do simple math to find out ratio would solve the problem easily.
So Ni is number of items you have to distribute, B sum of all boxes capacity(ie c1+c2+...+cn)
So R = Ni/B would be your ration.
R*cn would be number of items you would want to put into box n
Example:
you have total of 8 items. and 2 boxes capacity 4, 12(N1 = 16).
R = 8/(4+12) = 1/2
for box would have R*4 = 2
second box would have R*12 = 6
Of course you would have to handle rounding issues, there will be +/-1 items in the boxes.
PS
For fixing rounding issue you will do following.
you create a variable sumSoFar = 0 //initial value
box1 contains R*c1
then you add sumSoFar+=Math.round(R*c1)
box2 contains Math.round(R*c2)
then you add sumSoFar+=Math.round(R*c2)
for last box you put N1-sumSoFar So you distribute all values.
here is the code:
static int[] distribute(int[] boxes, int items) {
int[] result = new int[boxes.length];
int sumSoFar = 0;
int totalCapacity = 0;
for (int box : boxes) {
totalCapacity += box;
}
float R = (float) items / totalCapacity;
for (int i = 0; i < boxes.length - 1; i++) {
int box = boxes[i];
result[i] = Math.round(R * box);
sumSoFar += result[i];
}
result[boxes.length - 1] = items - sumSoFar;
return result;
}
Calling:
System.out.println(Arrays.toString(distribute(new int[]{1, 2}, 10)));
System.out.println(Arrays.toString(distribute(new int[]{4, 12}, 8)));
Results:
[3, 7]
[2, 6]
Two approaches come to mind
Optimal Rounding
Treat the problem like an optimal rounding problem. Since you want the items distributed in the boxes "in ratio of their capacity", then for each box compute their share which is "capacity / sum of all capacities". Then multiply that share by the number of items. That'll usually give you a fractional number of items for each box. I assume your items are indivisible. Now you just have to determine how to "optimally round" these values. Here is one SO question that discusses how to do that. You can also search for "optimal rounding under integer constraints" to find several papers on the subject.
Fair Division
Treat the problem using fair division. The link covers numerous approaches (most are approximations). However, the key part will be how will each of your boxes ascribe a value to each item, so that the algorithms will know how to parcels the items. You can use a metric that is proportional to their capacity.
I am working on a bonus for one of my assignments. I'm supposed to create a really large array, but the user doesn't have to use all the slots in the array. Previously I used an enhanced for loop for a regular array that had all its indexes filled. I'm not really sure how to change that to fit the new criteria.
Whenever I enter the numbers in the tester, the toString returns the empty spots and the minimum value returns 0 because the empty spot's values are 0s.
public class NumberSetBonus
{
private int[] numbers;
private int count;
/**
* Constructs an empty NumberSet of a specified size
* #param size the number of elements in the set
*/
public NumberSetBonus(int size)
{
numbers = new int[size];
count = 0;
}
/**
* addNumber adds a number to the number set
* #param num new number
*/
public void addNumber(int num)
{
numbers[count] = num;
count++;
}
/**
* getMin finds the minimum value stored in the NumberSet
* #return the minimum value
* precondition: array is full of values
*/
public int getMin()
{
int min = numbers[0];
for(int n : numbers)
if(n < min)
min = n;
return min;
}
/**
* getMax finds the maximum value stored in the NumberSet
* #return the maximum value
* precondition: array is full of values
*/
public int getMax()
{
int max = numbers[0];
for(int n : numbers)
if(n > max)
max = n;
return max;
}
/**
* find determines whether a specified value exists in the set.
* #param num the number to find
* #return whether the value exists
*/
public boolean find(int num)
{
boolean find = true;
for(int n : numbers)
if(n == num)
find = true;
return find;
}
/**
* getSum calculates the sum of the values in the set.
* #return the sum
*/
public int getSum()
{
int sum = 0;
for(int n : numbers)
sum += n;
return sum;
}
/**
* getMean calculates the mean of the values in the set.
* #return the mean as a double
* precondition: array is full of values
* NOTE: use the length field of the array
*/
public double getMean()
{
return getSum() / (double) numbers.length;
}
/**
* count counts the occurrence of a specified number within the set.
* #param num the number to find
* #return the number of times num occurs in the set
*/
public int count(int num)
{
int quantity = 0;
for(int n : numbers)
if(n == num)
quantity++;
return quantity;
}
/**
* toString returns a String containing the values in the set on a
* single line with a space between each value.
* #return the String version of the set
*/
public String toString()
{
String set = " ";
for(int n : numbers)
set += n + " ";
return set;
}
}
Here's my tester, where I ask for the user's input, and where the toString() returns the 0s
public class NumberSetBonusTester
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
final int LENGTH = 100;
NumberSetBonus list = new NumberSetBonus(LENGTH);
int arraySize = 0;
System.out.print("You can enter up to 100 numbers in this array. \nType in a negative number if you want to stop adding numbers.\nEnter a number: ");
while(arraySize < LENGTH)
{
int number = input.nextInt();
if(number <= 0)
break;
list.addNumber(number);
arraySize++;
}
System.out.print("\nset 1:\t\t");
System.out.println(list);
System.out.println("list sum:\t" + list.getSum());
System.out.println("list mean:\t" + list.getSum() / arraySize);
System.out.println("list max:\t" + list.getMax());
System.out.println("list min:\t" + list.getMin());
System.out.println();
System.out.print("Enter a number to find ==> ");
int searchNum = input.nextInt();
if (list.find(searchNum))
System.out.println(searchNum + " is in the set " + list.count(searchNum) + " times");
else
System.out.println(searchNum + " is not in the set");
}
}
You can simply change all your for loops to the form for (int i = 0; i < count; i++) - this way the loops will only loop the numbers that were actually set, not all numbers in the array.
BTW: If you ever need some variable-sized array in the future you can use a List (from the java.util package). In your example I would use an ArrayList<Integer>. This is a list that uses an array internally, but increases its size if the array gets too small (by creating a new array and copying the contents).
In this project, I am trying to write a program that creates a 9x9 Sudoku board with 9 3x3 subgrids, along with a header row and column that lists the letters a to i. The program compiles correctly, but when I hit run, it gives the following error:
java.lang.ArrayIndexOutOfBoundsException: 0
at Sudoku.main(Sudoku.java:218)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at `enter code here`edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)
Now, when I submitted this, the grading program stated that my print(), rowsComplete(), columnsComplete(), and isComplete() methods were incorrect, and that my main() was throwing a java.util.NoSuchElementException. I am confused as to why this is happening. Here is my code for Java, as well as notes on what exactly the methods are supposed to be doing.
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class Sudoku
{
public static final int SIZE = 9;
public static final int SUBGRID = 3;
public int[][] game;
public int[][] originalGame;
public Sudoku(String puzzleFile)
{
try
{
game = new int[SIZE][SIZE];
originalGame = new int[SIZE][SIZE];
File file = new File(puzzleFile);
Scanner in = new Scanner(file);
int i = 0;
int j = 0;
int k;
for (i = 0; i<SIZE; i++){
for (j = 0; j<SIZE; j++){
k = in.nextInt();
game[i][j]=k;
originalGame[i][j] = k;
}
}
}
catch (FileNotFoundException e)
{
System.out.println("FileNotFound: " + e.getMessage());
}
}
public void setZero(int[] array)
{
int i = 0;
for (i = 0; i < array.length; i++)
{
array[i] = 0;
}
}
/**
* This method determines whether the ints 1-9 are present exactly
* once in each row. Sets valSeen[i] = 1 if it sees i. If at any
* point valSeen[i] is already 1, the rows are not complete because of
* duplicate entries.
*
* If game[x][y] == -1, there is a blank entry so the row cannot be complete.
*
* #param valSeen: an array of ints that serve as flags to indicate whether
* their entry has been seen before or not.
*
* returns: true if each digit 1-9 is present in the row exactly once, else false
**/
public boolean rowsComplete(int[] valSeen)
{
int temp;
int k = 0;
for(int rows = 0; rows<SIZE; rows++){
for(int cols = 0; cols<SIZE; cols++){
if(game[rows][cols]==-1)
return false;
temp = game[rows][cols];
valSeen[temp-1]++;
}
for(k=0; k<valSeen.length; k++){
if(valSeen[k]!=1)
return false;
else return true;
}
setZero(valSeen);
}
return true;
}
/**
* This method determines whether the ints 1-9 are present exactly
* once in each column. Sets valSeen[i] = 1 if it sees i. If at any
* point valSeen[i] is already 1, the rows are not complete because of
* duplicate entries.
*
* If game[x][y] == -1, there is a blank entry so the row cannot be complete.
*
* #param valSeen: an array of ints that serve as flags to indicate whether
* their entry has been seen before or not.
*
* returns: true if each digit 1-9 is present in the column exactly once, else false
**/
public boolean columnsComplete(int[] valSeen)
{
int temp;
int k = 0;
for(int cols = 0; cols<SIZE; cols++){
for(int rows = 0; rows<SIZE; rows++){
if(game[rows][cols]==-1)
return false;
temp = game[rows][cols];
valSeen[temp-1]++;
}
for(k=0; k<valSeen.length; k++){
if(valSeen[k]!=1)
return false;
else return true;
}
setZero(valSeen);
}
return true;
}
/**
* This method determines whether the ints 1-9 are present exactly
* once in each subgrid. Sets valSeen[i] = 1 if it sees i. If at any
* point valSeen[i] is already 1, the rows are not complete because of
* duplicate entries.
*
* If game[x][y] == -1, there is a blank entry so the row cannot be complete.
*
* #param valSeen: an array of ints that serve as flags to indicate whether
* their entry has been seen before or not.
*
* returns: true if each digit 1-9 is present in each subgrid exactly once, else false
**/
public boolean subgridsComplete(int[] valSeen)
{
int temp;
for(int rows=0; rows<SIZE; rows+=3){
for (int cols=0; cols<SIZE; cols+=3){
for(int subrows=0; subrows<SUBGRID; subrows++){
for (int subcols=0; subcols<SUBGRID; subcols++){
temp= game[rows+subrows][cols+subcols];
if(temp==-1)
return false;
else
valSeen[temp-1]++;
}
}
for(int k=0; k<valSeen.length; k++){
if(valSeen[k]!=1)
return false;
else return true;
}
setZero(valSeen);
}
}
return true;
}
// Create the array valSeen here. I suggest making it = new int[SIZE+1].
// That way, it will have indexes 0-9, so the ints 1-9 can go into indexes
// 1-9 instead of mapping them to 0-8 by subtracting 1.
// Call rowsComplete(), columnsComplete(), and subgridsComplete().
// Be SURE to initialize valSeen to 0 before each method call by using setZero().
public boolean isComplete()
{
int [] valSeen = new int[SIZE+1];
setZero(valSeen);
if(rowsComplete(valSeen) && columnsComplete(valSeen) && subgridsComplete(valSeen))
return true;
else
return false;
}
public String makeHeader()
{
String header = " ";
for (int x = 97; x<106; x++)
header += ((char)x) + " | " + " ";
return header;
}
/**
* Prints out the grid. Each entry has a space to either side, columns are separated by '|'
* within the grid / between the header and the grid but not externally. See the specification
* for a detailed example. -1 is replaced with '_'.
*
* Remember that 'a' + 1 = 'b'
*
* Prints the grid to standard out.
**/
public void print()
{
System.out.println(makeHeader());
for(int rows=0; rows<SIZE; rows++){
System.out.print(" "+(char)('a'+rows));
for (int cols=0; cols<SIZE; cols++){
if (game[rows][cols]==-1)
System.out.print(" | _");
else
System.out.print(" | "+game[rows][cols]);
}
System.out.println();
}
}
public void move(String row, String col, int val)
{
int rowNumber = ((int)(row.charAt(0)-97));
int columnNumber = ((int)(col.charAt(0)-97));
if(originalGame[rowNumber][columnNumber]==-1)
game[rowNumber][columnNumber]=val;
}
public static void main(String[] args)
{
Sudoku puzzle = new Sudoku(args[0]);
Scanner s = new Scanner(System.in);
System.out.println("");
boolean gameplay = true;
while (gameplay){
puzzle.print();
if(puzzle.isComplete()){
System.out.println("Puzzle Complete!");
gameplay=false;
} else {
System.out.println("Puzzle Incomplete!");
System.out.println("Enter new value <row col val> :");
String rowv = s.next();
String colv = s.next();
int valv = s.nextInt();
puzzle.move(rowv, colv, valv);
}
}
}
}
In main method,
Sudoku puzzle = new Sudoku(args[0]);
Your program need an argument to initialize Sudoku which is being taken from user.
String[] args in main is a array of arguments for program which is given as parameters while starting program.
For you program, you'll have to start your Sudoku.class as
java Sudoku argument
You'll have to run you program with argument, else you'll get java.lang.ArrayIndexOutOfBoundsException: 0
I'm trying to make a string binary search program. Trouble is I don't remember a straight forward way to convert a string array into a Integer array.
I've written a long and complicated way to convert them. However Netsbeans is saying my string array identifier is expected.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication3;
/**
*
* #author Ivan Beazer
*/
import java.io.*;
/**
This program demonstrates the search method in
the IntBinarySearcher class.
*/
public class BinarySearchTest
{
private static String aString;
// Convert string array to string
public static String arrayToString2(String[] words, String aString)
{
StringBuilder result = new StringBuilder();
if (words.length > 0)
{
result.append(words[0]);
for (int i=1; i<words.length; i++)
{
result.append(aString);
result.append(words[i]);
}
}
return result.toString();
}
public static void main(String [] args) throws IOException
{
int result, searchValue;
String input;
// A String array of words to search.
// This is the error. netbeans says identifier is expected.
String[] words = {"Jake", "Jerry". "Bill", "Lousie", "Goku", "Ivan", "John", "sarah", "kim"};
// convert string to int array
int[] numbers = new int[aString.length()];
for(int i=0; i<aString.length(); i++)
numbers[i] = Character.getNumericValue(aString.charAt(i));
// Create the console input objects.
InputStreamReader reader =
new InputStreamReader(System.in);
BufferedReader keyboard =
new BufferedReader(reader);
// First we must sort the array in ascending order.
IntQuickSorter.quickSort(numbers);
do
{
// Get a value to search for.
System.out.print("Enter a value to search for: ");
input = keyboard.readLine();
searchValue = Integer.parseInt(input);
// Search for the value
result = IntBinarySearcher.search(numbers, searchValue);
// Display the results.
if (result == -1)
System.out.println(searchValue + " was not found.");
else
{
System.out.println(searchValue + " was found at " +
"element " + result);
}
// Does the user want to search again?
System.out.print("Do you want to search again? (Y or N): ");
input = keyboard.readLine();
} while (input.charAt(0) == 'y' || input.charAt(0) == 'Y');
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication3;
/**
*
* #author Devon B
*/
/**
The IntBinarySearcher class provides a public static
method for performing a binary search on an int array.
*/
public class IntBinarySearcher
{
/**
The search method performs a binary search on an int
array. The array is searched for the number passed to
value. If the number is found, its array subscript is
returned. Otherwise, -1 is returned indicating the
value was not found in the array.
#param array The array to search.
#param value The value to search for.
*/
public static int search(int[] array, int value)
{
int first; // First array element
int last; // Last array element
int middle; // Mid point of search
int position; // Position of search value
boolean found; // Flag
// Set the inital values.
first = 0;
last = array.length - 1;
position = -1;
found = false;
// Search for the value.
while (!found && first <= last)
{
// Calculate mid point
middle = (first + last) / 2;
// If value is found at midpoint...
if (array[middle] == value)
{
found = true;
position = middle;
}
// else if value is in lower half...
else if (array[middle] > value)
last = middle - 1;
// else if value is in upper half....
else
first = middle + 1;
}
// Return the position of the item, or -1
// if it was not found.
return position;
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication3;
/**
*
* #author Devon B
*/
/**
The IntQuickSorter class provides a public static
method for performing a QuickSort on an int array.
*/
public class IntQuickSorter
{
/**
The quickSort method calls the doQuickSort method
to sort an int array.
#param array The array to sort.
*/
public static void quickSort(int array[])
{
doQuickSort(array, 0, array.length - 1);
}
/**
The doQuickSort method uses the QuickSort algorithm
to sort an int array.
#param array The array to sort.
#param start The starting subscript of the list to sort
#param end The ending subscript of the list to sort
*/
private static void doQuickSort(int array[], int start, int end)
{
int pivotPoint;
if (start < end)
{
// Get the pivot point.
pivotPoint = partition(array, start, end);
// Sort the first sub list.
doQuickSort(array, start, pivotPoint - 1);
// Sort the second sub list.
doQuickSort(array, pivotPoint + 1, end);
}
}
/**
The partiton method selects a pivot value in an array
and arranges the array into two sub lists. All the
values less than the pivot will be stored in the left
sub list and all the values greater than or equal to
the pivot will be stored in the right sub list.
#param array The array to partition.
#param start The starting subscript of the area to partition.
#param end The ending subscript of the area to partition.
#return The subscript of the pivot value.
*/
private static int partition(int array[], int start, int end)
{
int pivotValue; // To hold the pivot value
int endOfLeftList; // Last element in the left sub list.
int mid; // To hold the mid-point subscript
// Find the subscript of the middle element.
// This will be our pivot value.
mid = (start + end) / 2;
// Swap the middle element with the first element.
// This moves the pivot value to the start of
// the list.
swap(array, start, mid);
// Save the pivot value for comparisons.
pivotValue = array[start];
// For now, the end of the left sub list is
// the first element.
endOfLeftList = start;
// Scan the entire list and move any values that
// are less than the pivot value to the left
// sub list.
for (int scan = start + 1; scan <= end; scan++)
{
if (array[scan] < pivotValue)
{
endOfLeftList++;
swap(array, endOfLeftList, scan);
}
}
// Move the pivot value to end of the
// left sub list.
swap(array, start, endOfLeftList);
// Return the subscript of the pivot value.
return endOfLeftList;
}
/**
The swap method swaps the contents of two elements
in an int array.
#param The array containing the two elements.
#param a The subscript of the first element.
#param b The subscript of the second element.
*/
private static void swap(int[] array, int a, int b)
{
int temp;
temp = array[a];
array[a] = array[b];
array[b] = temp;
}
}
Look after the string "Jerry":
String[] words = {"Jake", "Jerry". "Bill", "Lousie", "Goku", "Ivan", "John", "sarah", "kim"};
You have a dot ( . ) instead of a comma ( , )