Integer variable not following while loop conditions - java

I've been having an issue with my code concerning arrays and int variables. In the section that I have issues with, I'm trying to check if an array (in which the user inputs their own integers) is in an increasing order, and if it is in an increasing order, the array is printed; if not, an error message is displayed. I am trying to do this using int two variables, one called c1 and another called orderCheck1 (both initialized to 0).
int[ ] list1 = new int [10000];
int a1 =0;
int b1 =0;
int c1 =0;
int value1;
int orderCheck1 =0;
while (a1 ==0){
if (b1 < list1.length){
value1 = scan.nextInt();
//checks to see if value entered is positive
if (value1 >=0){
list1[b1] = value1;
b1++;
}
else{
a1 =1;
}
}
}
while (c1 <(list1.length-1)){
if (list1[c1] >list1[(c1+1)]){
orderCheck1 =1;
}
c1++;
}
if (orderCheck1 ==0){
for (int i =0; i < b1; i++){
System.out.print (list1[i] + " ");
}
}
else{
System.out.println ("ERROR: One or both arrays are not in an increasing order.);
}
Basically, if a number in the array is larger than the number following it, orderCheck will become 1. Later in the code, it checks if orderCheck1 is either zero or one. If orderCheck1 is zero, then the ints in the array are printed; if it is one, then the error message is displayed.
The issue is, no matter what I enter, orderCheck1 always becomes a one, so the error message is always printed. What is wrong with my code?
Note: When the user enters values into the array, they are supposed to enter a negative number to stop entering values.

The main problem, I believe, is that you've allocated a list of 10000 elements, and you don't use them all. Java initializes the elements to 0. (Note that in some other languages, a construct like this could initialize the elements to random garbage values.)
You then write a loop that inputs numbers until the user enters a negative number. This will set the first n elements of the loop for some number n. But the remaining elements do not get chopped off the array. They are still there, and they are still 0.
This causes a problem for this loop:
while (c1 <(list1.length-1)){
if (list1[c1] >list1[(c1+1)]){
orderCheck1 =1;
}
c1++;
}
Note that list1.length is still 10000, even though the user didn't enter 10000 values. Once an array is created with new int[10000] or something like that, that fixes the .length of the array. This length cannot be changed. That means c1 will go up to 9999, regardless of how many values were entered.
Therefore, at some point, you will hit a point where you start comparing to the 0 values that got put in the array when you created it. Since all the values the user entered are positive, that means list1[c1] > list1[c1+1] will be true when list[c1] is the last value entered, because list1[c1+1] will still be 0.
The solution is that instead of letting c1 go up to list1.length-1, you have to stop it when it gets to, I think, one less than the number of user entries. It looks like you already have a b1 that counts the number of entries, so the while needs to be changed to while (c1 <some-expression-that-uses-b1). I'll let you work on getting that upper limit right.
One more thing: When you have an array like this whose size isn't really known, it's better to use an ArrayList. Unlike an int[], an ArrayList<Integer> will grow as you add elements to it, and the size() method will return the actual number of elements added.

I would suggest a method:
static boolean isAscending(int[] nums) {
for (int i = 1; i < nums.length; i++)
if (nums[i - 1] > nums[i])
return false;
return true;
}
Note that this handles the edge case of arrays of size zero or one correctly.

Related

In this code, error showing "division by zero", for the condition inside the while loop. Why is this happening?

Here when I add System.out.println(j) inside the loop, the initial number is random, and the next outputs are huge values from 400000
Value of j is Initialized to 1, does while loop counts all int values unless mentioned?
public static void main(String[] args) {
int num = 31;
int j = 1, c = 0;
while (num != 0) {
//System.out.println(j);
if (num % j == 0) {
c += j;
}
j++;
}
System.out.println(c);
}
The only way that the loop could be exited in normal circumstances, is if num became 0. But you never reassign num to any other number, so it is always 31, so the loop won't end (in a regular manner).
What happens though is in your loop you're incrementing j on every pass. j is declared an int. ints have maximum values defined, after which they go to minimum value, so from maximum (positive) number, after another increase you get a minimum (negative) number. Then you count up till you reach 0. And then the exception is thrown as the application tries to divide by 0.
(see here: What happens when you increment an integer beyond its max value?)
The reason you see 400000 as the first displayed value is because the loops go so fast, that the console is not able to handle it gracefully, and you see just some of the outputs displayed.
Not sure what you're trying to achieve, but in order for this program to work differently, either change the loop condition or add a break statement inside - as mentioned in the comments.

What do array[] and array[i] operators do in Java?

I'm trying to teach myself coding, and I stumbled on an example I don't understand. Could someone give me an overview of what this code is supposed to do? I'm a bit confused about int a[] and what is later int a[i]. I know what an array is, but could someone please explain how this is being used in this context? Thank you in advance.
public class all {
public int select(int a[],int n,int x)
{
int i=0;
while(i<n && a[i]<x)
{
if(a[i]<0)
a[i]=-a[i];
i++;
}
return(a[i-1]);
}
}
This
if(a[i]<0)
a[i]=-a[i];
i++;
is he same like this
if(a[i]<0) {
a[i]=-a[i];
}
i++;
a[i] -> value at the position i, into the Array
if(a[i]<0) { -> if the value at position i is smaller than 0, also negative number
a[i]=-a[i]; -> replace the value with a reverse sign.
i++ -> increment loop Counter
Also what is done here: negative numbers convert to positive numbers.
while(i<n && a[i]<x) -> i = loop counter; if i smaller n and the value at position i in the array is smaller than x, then go into the loop.
return(a[i-1]); -> return the last value, that has been checked into the while loop
the method gets an array and two int args n and x (as a side note, I must say the names leave a lot to be desired...)
anyway, lets see what are the args for. they both are used in the while loop. the condition i<n tells us that n serves as upper limit to the iteration, while the condition a[i]<x tells us that x is used as upper limit to the values in the array.
so far, we can say:
select method receives an array, int arg specifying iteration-upper-limit and int arg specifying cell-value-upper-limit.
iterate over the array until you reach position specified by iteration-upper-limit or you reach a cell value that exceeds cell-value-upper-limit (which ever comes first)
can you continue to say what's being done inside the loop? it's fairly straightforward.
1.) a[] is the declaration of array.size is not defined.
2.)In a[i], i is the index number of the array...that means indicating the position of the element in array.
a[] is an array and we do not know its length. n must be lower than the length of a[] or it will throw an exception. It it traverses from the first element toward the last untill it one element is larger than x. it returns these element's absolute value which were traversed

How can two or more lists be traversed in O(N)

I have a question that doesn't seem possible to me. I have 2+ arrays which I have to compare for common values. I am supposed to do this in O(N) comparisons but can't think of a way. Specifically (k-1)N comparisons where k is the number of arrays. I've narrowed down how I can take multiple arrays and just merge them into a single array. I've gotten that the smallest array is the limiting factor so if I sort that I can save the most comparisons. After spending half the day staring at my screen I've even come up with a way to do this linearly if I discount any duplicates, but I have to keep duplicates So, as far as I know in order to compare any arrays you need at least 2 for loops which would be O(N^2) wouldn't it? I'm also not allowed to hash anything.
For example if I had {1,3,4,3,4,5} as a master and {1,1,3,5,9,3,7} and {3,5,8,4,0,3,2} as arrays to be compared I'd need to have a final of {3,3,5} since I can't get rid of any dupiclates.
I don't want anyone to write the code, I just need to know what I should be doing in the first place.
Use an array of ints. Taking your first list, for each element, set the value at that index to 1. So if the first element is 3, put 1 in array[3]. Now, we know that 3 is present in first list. Putting 1 will help you distinguish from a 3 that is present in the earlier list versus a 3 which is repeated in current list.
Iterate through all the other k-1 lists
For every element, check the value in array for that index
If the value is 0, set it to this list number
If the value is a number less than this list number, this number is a duplicate and has already appeared in a previous list.
If this number is equal to this list index it means this number already occurred in this list but not in previous lists, so not yet a duplicate.
The numbers that you are getting as duplicates, add them to another list.
Finish all iterations
Finally print the duplicates.
Original Wrong Answer
Create a HashSet<int>
Take all values from master and add to it - O(master list count)
Now just iterate through first and second arrays and see if their elements are in that HashSet - O(each list count)
If the lists are sorted, then it's relatively straightforward if you do something like this:
List<Integer> intersection = new ArrayList<>();
int i = 0;
int j = 0;
while (i < list1.size() && j < list2.size()) {
int a = list1.get(i);
int b = list2.get(j);
if (a < b) {
i++;
} else if (b < a) {
j++;
} else { // a == b
intersection.add(a);
i++;
j++;
}
}
On each iteration of the loop, the quantity i + j increases by at least 1, and the loop is guaranteed to be done when i + j >= list1.size() + list2.size(), so the whole thing does at most O(list1.size() + list2.size()) comparisons.

How can I (more) easily compare two sets of numbers?

I have sets of three numbers, and I'd like to compare numbers in a set to another set. Namely, that each number in the first set is less than at least one number in the other set. The caveat is that the next numbers in the first set must be less than a different number in the second set (i.e., {6,1,6} would work against {8,8,2}, but {6,2,6} against {8,8,2} wouldn't). I have a working method, but it's brute force and ugly.
If we have setA and setB, and each of those have elements a, b, and c:
if(setB.a < setA.a)
if(setB.b < setA.b)
if(setB.c < setA.c)
return true;
else if(setB.b < setA.c)
if(setB.c < setA.b
return true;
and so on...
EDIT: I just realized you said these sets are hardcoded at 3 values. This is a super general algorithm for sets of any size.
For a 3-value set, you can do the same dumping and sorting of set elements, and then do:
if(setB.a < setA.a)
if(setB.b < setA.b)
if(setB.c < setA.c)
return true;
return false;
======================================================
A general algorithm:
This is the most efficient way I can immediately think of to do this.
pseudocode (more pythonic than java, sorry-- hopefully the comments explain):
list l1 = set1.items() //get the items out
list l2 = set2.items()
l1 = sort(l1)
l2 = sort(l2) //sort the lists
int set2idx1 = l1[0].find_closest_greater_than_value(l2) //binary search or something
if set2idx1 exists:
l2 = l2[set2idx1+1:] //in python this means l2 is reassigned to a subarray of l2 starting at set2idx1+1 going to the end of l2
else:
return false
for(int i=1; i<l1.len; i++)
int set2idxi = l1[i].find_closest_greater_than_value(l2) //binary search or something
if set2idxi exists:
l2 = l2[set2idxi+1:]
else
return false
return true
comment if anything doesn't make sense
EDIT EDIT:
explanation of the general algorithm for any interested parties:
dump the set elements into arrays
sort those arrays
iterate through the first array, seeing if there is a value in the 2nd array that is greater than the current value. If so, get the index of that value and lop off everything before and including that index and reassign the 2nd array variable to what remains.
if there ever is no such value (either because it doesn't exist or you've run out of values to test, return false). Otherwise, at the end, return true.
The idea here is that since the arrays are sorted, you know that any element that is greater than the matched element in the 2nd array will be greater than the element you're testing against in the 1st array. So you can just chop off the lower values, and since you don't want to use the same value, you can chop off the one you found, too. If you ever return false you know it's because either there were no greater values, either because the numbers in array1 were all greater than the numbers in array2, or because there weren't enough numbers in array2 greater than the numbers in array1.
What about the following pseudocode?
Condition(A : Set, B : Set) : Bool =
Let a := max(A), b := min(B) In
// Namely, that each number in the first set is less than at least one number in the other set
If a <= b Then
// the next numbers in the first set must be less than a different number in the second set
Condition(without(A, a), without(B, b))
Else
False
EndIf
Where without(A, a) means the set A minus the set {a}
It seems that a List would do better than a Set since your example includes duplicate elements. Simply:
1) Sort the two lists.
2) Trim off the first few elements from the second list until the sizes of the first and second list are equal.
3) Directly compare list1[i] with list2[i] for each i.
Code:
import java.util.*;
class Main {
public static void main (String[] args) {
List<Integer> list1 = new ArrayList<Integer>();
List<Integer> list2 = new ArrayList<Integer>();
list1.add(3); list1.add(7); list1.add(7);
list2.add(8); list2.add(8); list2.add(2); list2.add(1); list2.add(5);
//algorithm:
Collections.sort(list1);
Collections.sort(list2);
List<Integer> list3 = list2.subList(list2.size() - list1.size(), list2.size());
System.out.println(list1.size() + " " + list3.size());
boolean pass = true;
for(int i = 0; pass && i < list1.size(); i++)
if(list1.get(i) >= list3.get(i))
pass = false;
System.out.println(pass);
}
}

Counting instances of a value in an array

Homework. Dice Game. I've got an array that represents five rolls of a die. Consider:
diceRoll[] = {6,3,3,4,5}. I would LIKE to create a SECOND array that has the counts of values from one to six contained in diceRoll[], (e.g., occurence[] = {0,0,2,1,1,1} for the diceRoll[] above.) but I fear I'm getting lost in nested loops and can't seem to figure out which value I ~should~ be returning. occurence[] is a global variable, and the intent is that the array will contain six values...the count of ones (at index [0]), twos (at [1]), threes (at [2]), etc.
So Far:
for(i=1;i<7;i++) /* die values 1 - 6
{
for(j=0;j<diceRoll.length;j++) /* number of dice
{
if (diceRoll[j] == i) /* increment occurences when die[j] equals 1, then 2, etc.
occurence = occurence + 1;
}
}
return occurence;
}
I cannot, however, get the occurence=occurence+1 to work. bad operand types for binary operator is my most common error. I suspect I need to increment occurence OUTSIDE one or both of the for loops, but I'm lost.
Guidance? or perhaps the one-line easy way to do this?
d
The easiest way I have to do this is to create the second array in order so that
occurrence[0] = # of 1's occurrence[1] = # of 2's and so on. Then this becomes a 1 loop method.
//method to return number of occurrences of the numbers in diceRolls
int[] countOccurrences(int[] diceRolls) {
int occurrence[] = new int[6]; //to hold the counts
for(int i = 0; i < diceRolls.length; i++) { //Loop over the dice rolls array
int value = diceRolls[i]; //Get the value of the next roll
occurence[value]++; //Increment the value in the count array this is equivalent to occurrence[value] = occurrence[value] + 1;
//occurrence[diceRolls[i]]++; I broke this into two lines for explanation purposes
}
return occurrence; //return the counts
}
EDIT:
Then to get the count for any particular value use occurrence[value-1]

Categories