ArrayIndexOutOfBoundsException when trying to reverse an array - java

This seems simple enough but I get the error "Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at reverse.main(reverse.java:28)"
I initially take inputs from the user to write an array, and then I want to print the array backwards. I understand there are other ways of doing this, but I mainly want to know why this is not working. Going through it line by line makes sense?
PS. If it's not a problem, is there any better way of doing this?
import java.util.Scanner;
public class reverse {
/**
* #param args
*/
public static void main(String[] args) {
System.out.printf("Enter the number of values in array: ");
Scanner scanner = new Scanner(System.in);
int n;
n = scanner.nextInt();
double[] a1 = new double[n];
int i;
System.out.printf("Enter the value in the array: ");
for (i = 0; i < n; i++){
Scanner scanner2 = new Scanner(System.in);
a1[i] = scanner2.nextInt();
}
double j;
double k;
for (i = 0; i < n/2; i++){
j = a1[i];
k = a1[n-i]; //error line;
a1[i]=k;
a1[n-i]=j;
}
for(i = 0; i < n; i++){
System.out.println(" "+a1[i]);
}}
}

When i = 0, n-i will result in n, which is one larger than the available indexes( 0 -> n-1 ).
for (i = 0; i < n/2; i++){
j = a1[i];
k = a1[n-i]; //error line;
a1[i]=k;
a1[n-i]=j;
}

Collections.reverse(Arrays.asList(array))
Will reverse an array for you, then just print its values out. It's great to do these kinds of problems as exercises but if you're ever woring in the industry it's usually better to rely on the Java API for trivial things like this. Probably going to be faster and a lot more simpler than anything you can come up with.

As said by Samhain, when i = 0, then n-i == n, which is greater than the last index of the array (since arrays start with index 0).
The simplest solution is to just subtract an additional 1 from n-i.
j = a1[i];
k = a1[n-i-1];
a1[i]=k;
a1[n-i-1]=j;
Also, creating a new Scanner is totally unnecessary. Just continue to use the first one you created.
for (i = 0; i < n; i++){
a1[i] = scanner.nextInt();
}
Finally, for what it's worth, if you're using nextInt you don't need to declare your array as a double[] (nor do j and k need to be doubles). You can just use ints.
Here's it running on ideone.

Related

Is there a way to loop through a variables using a 'for' loop?

int oct1 = scan.nextInt();
int oct2 = scan.nextInt();
int oct3 = scan.nextInt();
int oct4 = scan.nextInt();
for(int i=1; i<5; i++){
System.out.println(oct+i);
}
This is my code and basically, I'm just wondering how I would go about looping through each of the oct variables.
I obviously know that the current print wouldn't work, but is there a way to make it so that a for loop can print each variable without just using four lines to print them all?
Ideally to handle many values and iterate them you should use a List implementation, an ArrayList is one of them. This could be an alternative way, more scalable and efficient.
List<Integer> octList = new ArrayList<Integer>();
octList.add(scan.nextInt());
octList.add(scan.nextInt());
octList.add(scan.nextInt());
octList.add(scan.nextInt());
for (int i = 0; i < octList.size(); i++) {
System.out.println(octList.get(i));
}
You can store them in an array, and then reference them based on index:
int[] arr = new int[]{scan.nextInt(), scan.nextInt(), scan.nextInt(), scan.nextInt(), scan.nextInt()};
for(int i = 0; i < arr.length; i++){
System.out.println(arr[i]);
}
For local variables and method parameter it is not possible. You can use an Array or a List to store the values and iterate.
For instance, using array,
// Declare an array of size 4
int oct[] = new int[4];
// Take input from user 4 times
for(int i = 0; i < 4; i++){
oct[i] = scan.nextInt();
}
// Print the array
for(int i = 0; i < 4; i++){
System.out.println(oct[i]);
}
Also check Is there any way to loop though variable names?.
Oracle have a very good introductory tutorial on arrays.
Oracle Tutorial On Arrays
There are two ways using standard Arrays. In my first solution, I assume the values oct1 ... oct4 have been populated. However, after the following example is another solution that does not assume this and also takes input using Scanner.
int[] values ={oct1, oct2, oct3, oct4};
// Two examples:
// Using a 'for each' loop to display values
for(int value : values){
System.out.println(value);
}
// Using a standard 'for' loop to display values
for(int i; i < values.length; i++){
System.out.println(values[i]);
}
This solution uses an array and reads into it using the Scanner, but you must know how many values are to be read in advance or else you will need to learn lists.
int count = 4;
int[] values = new int[count];
Scanner scan = new Scanner(System.in);
// Using a standard for loop to read in values
for(int i; i < values.length; i++){
System.out.println("Enter a number");
values[i] = scan.nextInt();
}
// Using a standard 'for' loop. Assume this
// would come later in the program because
// you would otherwise read in and display
// the values in a single loop.
for(int i; i < values.length;i++){
System.out.println(values[i]);
}
Use a map to name the values:
Map<String, Integer> values = new LinkedHashMap<>();
for (int i = 1; i < 5; i++) {
values.put("oct" + i, scan.nextInt());
}
for (Map.Entry<String, Integer> value : values) {
System.out.println(value.getValue());
}
Or to output their name too:
for (Map.Entry<String, Integer> value : values) {
System.out.println(value.getKey() + " = " + value.getValue());
}
And to get them:
int v = values.get("oct2");
There are two ways using standard Arrays. In my first solution, I assume the values oct1 ... oct4 have been populated. However, below is a solution that does not assume this.
int[] values ={oct1, oct2, oct3, oct4};
//Two Examples:
//Using a for each loop
for(int value : values){
System.out.println(value);
}
//Using a standard for loop
for(int i; i < values.length;i++){
System.out.println(values[i]);
}
This solution assumes no array, but you must know how many values are to be read in advance or else you will need to learn lists. Remember to import scanner with import java,util.Scanner; at the top of the class file you are using this code.
int count = 4;
int[] values = new[count];
Scanner scan = new Scanner(System.in);
//Using a standard for loop
//Assume this would go later in the
//program or else use a single loop
//to read in and display the values.
for(int i; i < values.length;i++){
System.out.println("Enter a number");
values[i] = scan.nextInt();
}
//Using a standard for loop
for(int i; i < values.length;i++){
System.out.println(values[i]);
}

Knapsack solution for input of strings

I had an online coding test where the problem was described as below. I could not finish the question but did leave some comments on how to come up with a potential solution. I wanted to know what have been the best to solve this problem. The main issue I was having was splitting the given inputs as string and finding a suitable collection to put them in. Below is the question.
You want to send your friend a package with different things.
Each thing you put inside of a package has such parameters as index number, weight and cost.
The package has a weight limitation.
Your goal is to determine which things to put into the package so that the total weight is less than or equal to the package limit and the total cost is as large as possible.
You would prefer to send a package which has less weight if there is more than one package with the same price.
This is a variation of the Knapsack problem.
Input:
Your program should read lines from standard input. Each line contains the weight that a package can take (before the colon) and the list of things you need to pick from. Each thing is enclosed in parentheses where the 1st number is a thing's index number, the 2nd is its weight and the 3rd is its cost.
Max weight any package can take is <= 100.
There might be up to 15 things you need to choose from.
Max weight and max cost of any thing is <= 100.
Output:
For each set of things produce a list of things (their index numbers separated by comma) that you put into the package. If none of the items will fit in the package, print a hyphen (-).
Test 1
Input81 : (1,53.38,$45) (2,88.62,$98) (3,78.48,$3) (4,72.30,$76) (5,30.18,$9) (6,46.34,$48)
Expected Output 4
Test 2
Test Input 75 : (1,85.31,$29) (2,14.55,$74) (3,3.98,$16) (4,26.24,$55) (5,63.69,$52) (6,76.25,$75) (7,60.02,$74) (8,93.18,$35) (9,89.95,$78)
Expected Output 2,7
There might be up to 15 things you need to choose from. so you have possible combination 2^15 = 32,768. So you can
check every combination and find out which combination meet requirement.
Exampe: there is 3 (1,2,3) things.
then u can choose: (),(1),(2),(3),(1,2),(1,3),(2,3),(1,2,3).
Now need tho find which combination meet requirements.
Here is solution:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
String res[] = s.replaceAll("[^0-9.]+",";").split(";");
double target = Integer.parseInt(res[0]);
int n = (res.length-1) / 3;
int[] Index = new int[20];
double[] P = new double[20];
double[] W = new double[20];
int jj = 0;
for(int i = 1; i < res.length; i +=3){
Index[jj] = Integer.parseInt(res[i]);
W[jj] = Double.parseDouble(res[i+1]);
P[jj++] = Double.parseDouble(res[i+2]);
}
double result = 0;
int track = 0;
double resSum = 0;
for(int i =0; i< (1<<n); i++){
double sum = 0;
double weight = 0;
for(int j=0; j < n; j++){
if(((1<<j)&i) > 0){
sum+= P[j];
weight+=W[j];
}
}
if(weight <= target){
if(sum > resSum){
result = weight;
track = i;
resSum = sum;
}else if(sum == resSum && weight < result){
result = weight;
track = i;
}
}
}
jj = 0;
for(int i = 0; i < n; i++){
if(((1<<i)&track) > 0){
if(jj > 0){
System.out.print(",");
}
jj = 1;
System.out.print(Index[i]);
}
}
if(track == 0){
System.out.println("-");
}else {
System.out.println();
}
}

I didn't understand the statement in the for loop! can any one please elaborate this?

int[] a = new int[101];
int n = in.nextInt();
for(int i = 0; i < n; i++){
a[in.nextInt()]++;
}
a is an array that is initialized; the next line get's you the amount of numbers that will follow after that.
Assuming that in is an initialized Scanner, nextInt() will read the next int from the console. Usually on websites like codingames.com or apparently hackerrank use this construct to put in data for your code to test it.
In the loop the code will read an index to be used in the pre-initialized array to increase the value by one at that given index.
That is basically it. To make it clearer, you could write:
int[] a = new int[101];
int numberOfIntsToFollow = in.nextInt();
for(int i = 0; i < numberOfIntsToFollow; i++){
int x = in.nextInt();
a[x]++;
}

Moving Average Using User-Input Array

I need to write a program that calculates a moving average by a user inputted array. The first element of the array is the window size, and the input is terminated by a 0. The output values are printed with two digits after the decimal point.
Example input: 3 2 4 7 7 8 11 12 0
Corresponding Output: 4.33 6.00 7.33 8.67 10.33
(4.33 is average of 2,4,7 and 6 is average of 4,7,7 etc.)
Here's my code so far:
package movingaverage;
import java.util.Scanner;
public class MovingAverage {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
int sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i];
}
avg[0] = sum / 5;
int j = 1;
for (int i = 5; i < arr.length; i++) {
sum = sum + arr[i] - arr[i - 5];
avg[j++] = sum / 5;
}
}
}
I think I have the loop right, but I'm not sure how to get the array to end at 0.
This is a possible solution.
public class Test
{
private static final Scanner SCANNER;
static {
SCANNER = new Scanner(System.in);
}
public static final void main(final String... args) {
final String[] numbers = SCANNER.nextLine().trim().split(" ");
final int consideredElements = Integer.parseInt(numbers[0]);
float sum = 0;
int value = 0;
for (int i = 1; i < numbers.length; i++) {
sum = 0;
for (int k = 0; k < consideredElements; k++) {
value = Integer.parseInt(numbers[i + k]);
if (value == 0) {
return;
}
sum += value;
}
System.out.println(new BigDecimal(sum / consideredElements).setScale(2, RoundingMode.HALF_EVEN));
}
}
}
First, you are using 5 in a couple of places in your program, I see no justification for that. Could it be that your expectation of user input lead you to put 5 where the number you really should use, depends on user input? Maybe you should use the window size instead? I’m guessing a bit here.
Next, as #lppEdd pointed out, you are not reading the numbers from your input — only the window size.
Next, you are declaring your array of size n, which I believe was your window size, not your array size. I believe the real solution to this problem is using better and more explanatory variable names.
Your code does not compile since you have not declared the array avg that you try to store your moving average into.
Fifth, when you want your average as a double, you need to convert to double before dividing (this is a classic pitfall that has already generated many questions on Stack Overflow).
I hope this gets you a couple of steps further.

reading input into array without hard coding

So I was thinking that maybe other people might have had this problem. I'm a total beginner .I am using java to program for android so I can test on my phone. When I read in inputs from my array,
example:
int[] myArray = new int[5];
I tend to hard code the inputs into the array.
int input1= nextInt("input1");
int input2= nextInt("input2");
etc..
myArray[1]= input1;
myArray[2]= input2;
etc..
but this is time consuming, especially if the bounds of the array are higher.
ie.
int[] myArray = new int[50];
So my question is, how is this all done the shortest way possible? without the timely hard coding.
This is my suggestion if you know the input length:
int[] arr = new int[50];
for(int i = 0; i < arr.length; i++)
arr[i] = nextInt("input" + i);
Else I would suggest using a while-loop and an ArrayList.
You should consider using a for loop or while loop to save time and for repetitive actions.
e.g,
for(int counter = 0; counter < myArray.length; counter++)
{
myArray[counter] = counter;
}
Use loops:
for(int i=0; i<myArray.length; i++){
myArray[i] = nextInt("input" + (i + 1));; // or whatever...
}

Categories

Resources