Java Exception: Array indexes out of bounds - java

I was given a lab assignment where we were asked to fill an array of size 50. The first 25 elements had random distinct elements, and the remaining have to be each 26 . All we have to do is print the repeating element,which obviously is 26, using the Las Vegas Algorithm .
I wrote the program and since it's my first time at Java , I am stuck with an exception of Array indexes out of bounds.
I am also sure that there is nothing wrong with the algorithm, and please note that I first created a list and then converted it to array of Integer type.
Hoping for a helping hand.
The code is as follows :-
public class NewClass {
static Random randomGenerator = new Random();
public static void lasveg(Integer a[],int n)
{
int i,j;
boolean chk= true;
while(chk)
{
i=(randomGenerator.nextInt())%n+1;
j=(randomGenerator.nextInt())%n+1;
if((i!=j)&&(a[i].equals(a[j])))
System.out.println("The repeated element is : " + i);
}
}
public static void main(String[] args)
{
int i ;
Integer[] arr = new Integer[50] ; //used the Integer wrapper class instead of primitive int
ArrayList list = new ArrayList(50);
for (i=1; i<26; i++)
{
list.add(i) ;
}
Collections.shuffle(list);
for(i=26 ; i<51 ; i++)
{
list.add(26) ;
}
list.toArray(arr) ;
for(i=0 ; i<50 ; i++)
{
System.out.print(arr[i] + " ");
}
lasveg(arr,50);
}
}

The code has several issues:
randomGenerator.nextInt() could return negative numbers and you
can't use negative numbers as index for an array.
if you use % n+1 then you could get an index bigger than 49, which
should be the highest index in an array of length 50.
the third thing is that you have a endless loop, because you never
end the while(true)
If you change all that then your code could look like that:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
public class NewClass {
static Random randomGenerator = new Random();
public static void lasveg(Integer a[], int n) {
int i, j;
boolean chk = true;
while (chk) {
i = Math.abs(randomGenerator.nextInt()) % n ;
j = Math.abs(randomGenerator.nextInt()) % n ;
if ((i != j) && (a[i].equals(a[j]))){
System.out.println("The repeated element is : " + i);
break;
}
}
}
public static void main(String[] args) {
int i;
Integer[] arr = new Integer[50]; // used the Integer wrapper class
// instead of primitive int
ArrayList list = new ArrayList(50);
for (i = 1; i < 26; i++) {
list.add(i);
}
Collections.shuffle(list);
for (i = 26; i < 51; i++) {
list.add(26);
}
list.toArray(arr);
for (i = 0; i < 50; i++) {
System.out.print(arr[i] + " ");
}
lasveg(arr, 50);
}
}
Output:
24 20 19 14 13 16 10 7 22 18 12 15 2 6 3 25 17 8 1 21 4 5 11 23 9 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 The repeated element is : 26

If you call this function with n = 50 and your array a got 50 elements
public static void lasveg(Integer a[],int n)
{
int i,j;
boolean chk= true;
while(chk)
{
i=(randomGenerator.nextInt())%n+1;
j=(randomGenerator.nextInt())%n+1;
if((i!=j)&&(a[i].equals(a[j])))
System.out.println("The repeated element is : " + i);
}
}
Whats happen there is if the random number is (50*x)-1 % 50 + 1 you calling a[50] thats throwing an out of range exception.
You aint want to increase the term rand % n then you get a range from 0 to 49.

Your i and j variables are assigned a random number in the segment from 0 to n, including n
i=(randomGenerator.nextInt())%n+1;
j=(randomGenerator.nextInt())%n+1;
In Java the index of the last element of array of n elements is n-1, so there is a possibility, that this statement
if((i!=j)&&(a[i].equals(a[j])))
System.out.println("The repeated element is : " + i);
will cause the index out of bound exception.

The problem that you have here it's that you have to notice that arrays starts at position 0.
array[0];
So, when you use your method lasveg you are setting the number 50 and really trying to access to the position 51 where you do a[i] and a[j] here:
if((i!=j)&&(a[i].equals(a[j])))
To fix your problem you will have to do:
lasveg(arr,49);
Another solution it's to avoid the + 1 in your Random. Change this:
i=(randomGenerator.nextInt())%n+1;
j=(randomGenerator.nextInt())%n+1;
to this:
i=(randomGenerator.nextInt())%n;
j=(randomGenerator.nextInt())%n;
I expect it will be helpful for you!

Related

Creating a method that merges 2 arrays into one sorted array in ascending order in Java

For part of an assignment, I have to create a method that merges 2 arrays into one sorted array in ascending order. I have most of it done, but I am getting a bug that replaces the last element in the array with 0. Has anyone ever run into this problem and know a solution? Heres my code:
public static OrderedArray merge(OrderedArray src1, OrderedArray src2) {
int numLength1 = src1.array.length;
int numLength2 = src2.array.length;
//combined array lengths
int myLength = (numLength1 + numLength2);
// System.out.println(myLength);
OrderedArray mergedArr = new OrderedArray(myLength);
//new array
long[] merged = new long[myLength];
//loop to sort array
int i = 0;
int j = 0;
int k = 0;
while (k < src1.array.length + src2.array.length - 1) {
if(src1.array[i] < src2.array[j]) {
merged[k] = src1.array[i];
i++;
}
else {
merged[k] = src2.array[j];
j++;
}
k++;
}
//loop to print result
for(int x = 0; x < myLength; x++) {
System.out.println(merged[x]);
}
return mergedArr;
}
public static void main(String[] args) {
int maxSize = 100; // array size
// OrderedArray arr; // reference to array
OrderedArray src1 = new OrderedArray(4);
OrderedArray src2 = new OrderedArray(5);
// arr = new OrderedArray(maxSize); // create the array
src1.insert(1); //insert src1
src1.insert(17);
src1.insert(42);
src1.insert(55);
src2.insert(8); //insert src2
src2.insert(13);
src2.insert(21);
src2.insert(32);
src2.insert(69);
OrderedArray myArray = merge(src1, src2);
This is my expected output:
1
8
13
17
21
32
42
55
69
and this is my current output:
1
8
13
17
21
32
42
55
0
While merging two arrays you are comparing them, sorting and merging but what if the length of two arrays is different like Array1{1,3,8} and Array2{4,5,9,10,11}. Here we will compare both arrays and move the pointer ahead, but when the pointer comes at 8 in array1 and at 9 in array2, now we cannot compare ahead, so we will add the remaining sorted array;
Solution:-
(Add this code between loop to sort array and loop to print array)
while (i < numLength1) {
merged[k] = src1.array[i];
i++;
k++;
}
while (j < numLength2) {
merged[k] = src2.array[j];
j++;
k++;
}
To answer your main question, the length of your target array is src1.array.length + src2.array.length, so your loop condition should be one of:
while (k < src1.array.length + src2.array.length) {
while (k <= src1.array.length + src2.array.length - 1) {
Otherwise, you will never set a value for the last element, where k == src1.array.length + src2.array.length - 1.
But depending on how comprehensively you test the code, you may then find you have a bigger problem: ArrayIndexOutOfBoundsException. Before trying to use any array index, such as src1.array[i], you need to be sure it is valid. This condition:
if(src1.array[i] < src2.array[j]) {
does not verify that i is a valid index of src1.array or that j is a valid index of src2.array. When one array has been fully consumed, checking this condition will cause your program to fail. You can see this with input arrays like { 1, 2 } & { 1 }.
This revision of the code does the proper bounds checks:
if (i >= src1.array.length) {
// src1 is fully consumed
merged[k] = src2.array[j];
j++;
} else if (j >= src2.array.length || src1.array[i] < src2.array[j]) {
// src2 is fully consumed OR src1's next is less than src2's next
merged[k] = src1.array[i];
i++;
} else {
merged[k] = src2.array[j];
j++;
}
Note that we do not need to check j in the first condition because i >= src1.array.length implies that j is a safe value, due to your loop's condition and the math of how you are incrementing those variables:
k == i + j due to parity between k's incrementing and i & j's mutually exclusive incrementing
k < src1.array.length + src2.array.length due to the loop condition
Therefore i + j < src1.array.length + src2.array.length
If both i >= src1.array.length and j >= src2.array.length then i + j >= src1.array.length + src2.array.length, violating the facts above.
A couple other points and things to think about:
Be consistent with how you refer to data. If you have variables, use them. Either use numLength1 & numLength2 or use src1.length & src2.length. Either use myLength or use src1.array.length + src2.array.length.
Should a merge method really output its own results, or should the code that called the method (main) handle all the input & output?
Is the OrderedArray class safe to trust as "ordered", and is it doing its job properly, if you can directly access its internal data like src1.array and make modifications to the array?
The best way to merge two arrays without repetitive items in sorted order is that insert both of them into treeSet just like the following:
public static int[] merge(int[] src1, int[] src2) {
TreeSet<Integer> mergedArray= new TreeSet<>();
for (int i = 0; i < src1.length; i++) {
mergedArray.add(src1[i]);
}
for (int i = 0; i < src2.length; i++) {
mergedArray.add(src2[i]);
}
return mergedArray.stream().mapToInt(e->(int)e).toArray();
}
public static void main(String[] argh) {
int[] src1 = {1,17,42,55};
int[] src2 = {8,13,21,32,69};
Arrays.stream(merge(src1,src2)).forEach(s-> System.out.println(s));
}
output:
1
8
13
17
21
32
42
55
69

Getting distinct characters from a string

I know there is an easier way to solve this problem statement now. But this is something i tried and wasn't able to debug.
This is my code.
String str="java is a programming language";
int flag=0,k=0;
char unique[]=new char[256];
for(int i=0;i<str.length();i++){
for(int j=i+1;j<str.length();j++){
if(str.charAt(i)==str.charAt(j))
flag++;
}
System.out.println(flag); //printing flag values
if(flag==0){
unique[k]=str.charAt(i);
System.out.println(unique[k]); //printing array values
k++;
}
}
And this is my output.
Enter the sentence:
java is a programming language
0
j
5
5
9
12
13
13
15
18
19
19
20
20
23
23
25
26
26
26
27
29
29
29
30
30
31
31
31
31
31
Unique characters:
j
I want to understand from where these number values are getting printed. I was certain printing flag values and array values will give me single digit numbers. What are all these double digit numbers?
you just need to reset the counter(flag) before adding to it in the next iteration.
flag=0;
for(int j=i+1;j<str.length();j++){
if(str.charAt(i)==str.charAt(j))
flag++;
}
Your code has the following problems:
Not resetting the value of flag.
Printing flag for each value of i whereas you wanted to print it only on finding a unique character.
You are starting the loop with j from i + 1 and this way, you will not be able to compare the characters before the index, i + 1.
Some additional things you may also like to do are:
Filtering only non-blank characters.
Printing the array only up to the value of k.
Not fixing the size of unique[] to 256. If all characters in str are unique, the required size of unique[] will be equal to the length of str. Thus, the maximum required size of unique[] is equal to str.length(). However, it is always better to use a List if the size needs to be dynamic.
Store and print unique characters as follows:
public class Main {
public static void main(String[] args) {
String str = "java is a programming language";
int flag, k = 0;
char unique[] = new char[str.length()];// This array can have a maximum length equal to the length of str
for (int i = 0; i < str.length(); i++) {
flag = 0;
for (int j = 0; j < str.length(); j++) {
if (i != j && str.charAt(i) == str.charAt(j)) {
flag++;
}
}
if (flag == 0 && !String.valueOf(str.charAt(i)).isBlank()) {
unique[k] = str.charAt(i);
k++;
}
}
System.out.print("Unique characters: ");
for (int i = 0; i <= k; i++) {
System.out.print(unique[i] + (i < k - 1 ? "," : "\n"));
}
}
}
Output:
Unique characters: j,v,s,p,o,l,u,e
String str="java is a programming language";
int flag=0,k=0;
char unique[]=new char[256];
for(int i=0;i<str.length();i++){
flag = 0;
for(int j=i+1;j<str.length();j++){
if(str.charAt(i)==str.charAt(j))
flag++;
}
System.out.println(flag); //printing flag values
if(flag==0){
unique[k]=str.charAt(i);
System.out.println(unique[k]); //printing array values
k++;
}
}

Java calculate ISBN using for loop [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 5 years ago.
I am still new to Java, this question like: An ISBN-10 (International Standard Book Number)
consists of 10 digits: d1d2d3d4d5d6d7d8d9d10. The last digit, d10, is a checksum,
which is calculated from the other nine digits using the following formula:
(d1 * 1 + d2 * 2 + d3 * 3 + d4 * 4 + d5 * 5 +
d6 * 6 + d7 * 7 + d8 * 8 + d9 * 9) % 11
If the checksum is 10, the last digit is denoted as X according to the ISBN-10
convention. Write a program that prompts the user to enter the first 9 digits and
displays the 10-digit ISBN (including leading zeros). Your program should read
the input as an integer.
See my code below:
It is working but the result is not correct!
public static Scanner input;
public static void main(String[] args)
{
input = new Scanner(System.in);
System.out.print("Enter first 9 digit numbers: ");
int[] arr = new int[9];
int checkSum = 0;
for (int i = 0 ; i < arr.length; i++)
{
arr[i] = input.nextInt();
checkSum = (arr[i] * i) % 11;
}
System.out.print("The ISBN-10 Number is " );
for(int j = 0 ; j < arr.length; j++)
{
System.out.print(arr[j]);
}
if(checkSum == 10)
{
System.out.println("x");
}
else
{
System.out.println(checkSum);
}
I just want to use loop, make my method works. , i know how to use method without loop.
well. for JAVA
an array index start from 0. and Max index is length - 1.
if the index is not within this range. an arrayoutofbounds exception will be thrown
The problem is not that you are doing int i = 1 instead of int i = 0. The problem is that you changed i < arr.length; to i <= arr.length;. Since arr.length is 9, your code is trying to refer to arr[9] but arr only has elements arr[0] through arr[8].
First, review how we use arrays...
int[] I = new int[3];
The above creates an array with 3 spots in it. After instantiating the array, each element is based off of a 0-index. You only have I[0], I[1], and I[2] available (note this is three numbers) and trying to access I[3] will throw the error that you encountered in your program above: ArrayIndexOutOfBoundsException.
That being said, your loop is trying to access arr[9]. The highest index you have in the array is arr[8], because despite the array having 9 elements in it, it's 0-indexed.
Assuming you MUST have i starting from 1 for a homework assignment or something, change your code to:
public static Scanner input;
public static void main(String[] args)
{
input = new Scanner(System.in);
System.out.print("Enter first 9 digit numbers: ");
int[] arr = new int[9];
int checkSum = 0;
for (int i = 1 ; i <= arr.length; i++)
{
arr[i-1] = input.nextInt();
checkSum = (arr[i-1] * i) % 11;
}
System.out.print("The ISBN-10 Number is " );
for(int j = 1 ; j <= arr.length; j++)
{
System.out.print(arr[j-1]);
}
if(checkSum == 10)
{
System.out.println("x");
}
else
{
System.out.println(checkSum);
}
int[] arr = new int[9];
This means the array has 9 slots. And the numbering of those slots starts from 0. Thus,
arr[0] is the first slot
arr[1] is the second slot
The last slot would be arr[8]. But in the following code you are iterating till i is equal to 9 which does not exist.
for (int i = 1 ; i <= arr.length; i++)
{
arr[i] = input.nextInt();
checkSum = (arr[i] * (i+1)) % 11;
}
This results in the ArrayIndexOutOfBoundsException. Change for (int i = 1 ; i <= arr.length; i++) to for (int i = 0 ; i < arr.length; i++)

Finding a missing number in an array that uses a random generator

I'm trying to make it so the random generator doesn't produce the same number in the array. I also don't know how to find the missing number. I tried the if statement, and it works, but it repeats.
The question problem "find the missing number in an array. The array consists of numbers from 1 to 10 in random sequence. One of the numbers in the array is absent and you must find it. Use one loop. An example {5,6,9,4,1,2,8,3,10} – the result will be: 7
import java.util.Random;
public class questionThree
{
public static void main(String[] args)
{
int [] numbers = new int [10];
Random rand = new Random();
int numArr = 1;
for (int i = 1; i < 9; i++)
{
int n = rand.nextInt(10) + 1;
numbers[i] = n;
if (numbers[i] == numArr)
numArr++;
else
System.out.println("The missing num is " +numArr);
}
for(int val : numbers)
{
System.out.println("The next value is " +
val);
}
}
}
Assumption:
Numbers are unique
Only one entry is missing
number ranges from [1, 10] inclusive.
Solution
return 55 - Arrays.stream(yourArr).sum();
This is with O(n) runtime and O(1) space complexity.
If we break assumptions.
You will need O(N) space to figure out which entries are missing. To hold the marker either you can use List or BitSet or 2 bytes and manage it by hand. N is here the random number generation width.
There seems to be no mention on using a temporary data structure.
You can either sort the array and find the missing number, OR use a temporary sorted data structure.
You are conflating two things: the generator algorithm for a problem case and the solution to the problem itself. You shouldn't be interested in how the "random array" is generated at all (unless you want to test your solution). What you certainly shouldn't do is try to write the code that solves the problem in the method that generates the sample array.
If you want a randomly sorted list, Collections.shuffle will handle that for you. If you want a list without a single element, just generate a list of all elements 1..n and then remove the randomly selected number (then shuffle). So much for the generator. As for the solution, there are many methods to do it, someone already suggested using the sum, that's a perfectly valid solution.
It seems you are looking for this code.
import java.util.Random;
public class questionThree
{
public static void main(String[] args)
{
int [] numbers = new int [9];
Random rand = new Random();
int numArr = 1;
numbers[0] = rand.nextInt(10) + 1;
for (int i = 1; i < 9; i++)
{
int n = rand.nextInt(10) + 1;
numbers[i] = n;
int x =0;
while(x<i){
if(numbers[x] == n){
i = i-1;
break;
}
x++;
}
}
int sum = 0;
for (int val : numbers) {
sum = sum + val;
System.out.println("The next value is " +
val);
}
System.out.println("Missing number is " + (55 - sum));
}
}
Output is -
The next value is 6
The next value is 2
The next value is 8
The next value is 1
The next value is 4
The next value is 3
The next value is 9
The next value is 10
The next value is 7
Missing number is 5
I am generating 9 Numbers between(1 to 10) randomly and then printing which number is missing among them.
You have two options:
The way I did it in the code below: setting the random array without repeating the same number. And then a for loop from 1 to 10 and check if that number exist in the array.
You know that 1 + 2 + 3 + 2 + 3 + 4 + 5 + 6 + 8 + 9 + 10 = 55. So if you get the sum of all ints in the array you will have 55 - (the missing number). So now the missing number = 55 - sum.
This is the code I did (first method):
import java.util.Random;
public class questionThree
{
public static void main(String[] args)
{
int [] numbers = new int [9];
Random rand = new Random();
for (int i = 0; i <9; i++)
{
//setting random numbers in array without repeating
numbers[i] = checkForANumber(rand, numbers, i);
}
//print all nums
for(int val: numbers) System.out.println("The next value is " +
val);
for (int i = 1; i <= 10; i++)
{
boolean exist = false;
for(int val : numbers)
{
if(val == i){
exist = true;
}
}
if (!exist) System.out.println("The missing number is " + i);
}
}
private static int checkForANumber(Random rand, int[] numbers, int i){
int n = rand.nextInt(10) + 1;
boolean NumAlreadyExist = false;
for(int j = 0; j < i; j++)
{
if(numbers[j] == n){
NumAlreadyExist = true;
}
}
if(NumAlreadyExist) return checkForANumber(rand, numbers, i);
else return n;
}
}
Output:
The next value is 9
The next value is 3
The next value is 8
The next value is 6
The next value is 7
The next value is 10
The next value is 4
The next value is 2
The next value is 1
The missing number is 5

Java Bubble Sort Acting Strange

I have a function here for bubble sort using Java and this code does work and sort an array. However, the issue is that I have no idea how it's sorting it because it does not seem like standard bubble sort.
public static void swap (int [ ] data, int index1, int index2)
// POST: elements at indexes are exchanged
{ int temp = data[index1]; // temporary to hold first value
data[index1] = data[index2];
data[index2] = temp;
}
public static void bubbleSort (int [ ] data)
// POST: elements in data array are sorted in ascending order
{ for (int ct1=0; ct1<data.length-1; ct1++) // outer loop moves one element into place
{ for (int ct2=0; ct2<data.length-1-ct1; ct2++)
if (data[ct2] > data[ct2+1]) // swap if element on left bigger than right
swap (data, ct2,ct2+1);
for (int i = 0; i < data.length; i++) System.out.print(data[i] + " ");
System.out.println();
}
}
The bubble sort I understand would take an array {40, 90, 10, 60, 20} and compare the 0th and 1st index. If the 0th index is greater than the 1st index then they would swap. Then, in this case, 40 and 90 would stay where they are and then the 1st and 2nd index would be compared, resulting in 90 and 10 swapping. This would continue n - 1 times where n is the length of the array.
The problem is, using this function seems to give the output:
Bubble sort:
Starting array: 40 90 10 60 20
40 10 60 20 90
10 40 20 60 90
10 20 40 60 90
10 20 40 60 90
Can anybody help explain this please?
It seems to be comparing arbitrary values and does not check the 40 and 90 like it should.
it will be swap until the end in a one loop with ct2.
inside loop ,will be going 4 times .
it is like a rock falling into water.
Engilsh is poor ,sorry~
Inside your bubbleSort method, you are starting an array from 0 upto the length of array - 1. Instead just make is simple and run it in reverse like this:
public static void bubbleSort(int [] data) {
int k;
for (int m = data.length; m >= 0; m--) {
for (int i = 0; i < data.length - 1; i++) {
k = i + 1;
if (array[i] > array[k]) {
swapNumbers(i, k, array);
}
}
// Time to test this new array here:
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + ", ");
}
System.out.println("\n");
}
}
Check if your solution is printed correctly and let me know
Your bubble sort is behaving the way you expect it too.
It is sorting lowest to highest in reverse order (i.e. last column is set first)
I think the problem you are having is that the output sample frequency
does not match what is going on in your head.
if you change the code slightly
public static void swap (int [ ] data, int index1, int index2){
int temp = data[index1];
data[index1] = data[index2];
data[index2] = temp;
}
public static void bubbleSort (int [ ] data) {
for (int ct1=0; ct1<data.length-1; ct1++) {
for (int ct2=0; ct2<data.length-1-ct1; ct2++) {
if (data[ct2] > data[ct2 + 1]) {
swap(data, ct2, ct2 + 1);
// non functional change to move sampling point
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + " ");
}
System.out.println();
}
}
}
}
public static void main(String[] args) {
bubbleSort(new int[]{40,90,10,60,20});
}
this produces the output
40 10 90 60 20
40 10 60 90 20
40 10 60 20 90
10 40 60 20 90
10 40 20 60 90
10 20 40 60 90
which is what I think you expect to see.

Categories