Find name in Arraylist, then transfer contents to an array? - java

I want to find my name in an ArrayList of students, then transfer my selection of 50 choices to a new array called myChoices (will later be compared against others for matches). The Student class contains a name and an ArrayList of choices. Here is the relevant loop:
int matches[] = new int[students.size()];
int myChoices[] = new int[students.get(0).getChoices().size()];
for(int i = 0; i < students.get(i).getChoices().size(); i++){
if(students.get(i).getName().equals("Garrett M")){
myChoices[i] = students.get(i).getChoices().get(i);
}
}
for(int i = 0; i < myChoices.length; i++){
System.out.println(myChoices[i]);
}
In the last loop, I'm just trying to print my choices, which come out as something like this:
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
(That's not 50, but you get the gist of it -- in the output there's about 49 zeros and one 1.) The actual output should begin with 1 and be a mixture of 0,1, and -1:
1 -1 1 1 1 1 0 1 1 0 0 0 1 1 0 1 0 0 1 1 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 0 1 -1 0 1 0 0 0 0 1 1 1 1 0 1
Any idea where I could be going wrong?

You are using the same index i for both the students List and the students.get(i).getChoices() List. That's probably wrong.
You probably need a nested loop:
for(int i = 0; i < students.size(); i++) { // iterate over the students to find the one
// having the required name
if(students.get(i).getName().equals("Garrett M")){
// iterate over the choices of the found student and collect them into the array
for (int j = 0; j < students.get(i).getChoices().size; j++) {
myChoices[j] = students.get(i).getChoices().get(j);
}
break;
}
}

By writing if statement inside loop you are only setting that particular element of mychoices[] array which matches with your name(Garrett M) rest all array element will remain as it is that is why you are getting 49 Zeros and 1 ones.

At times, imperative programming may turn out to be confusing with a lot of for loops. From ages, we have been using for far too many times in our code. With Java 8, one can code in declarative style. A code written in declarative style is more easy to read and understand.
Just adding to what #Eran has answered, I'll try to simplify the same solution using Java 8 Stream APIs. Some day, this might come in handy for you, if not today.
The problem in hand is to get the choices of a particular student and add those choices in an array(or Collection).
This can be done as follows:
List<Integer> myChoicesList = students.stream()
.filter(student -> student.getName().equals("Garrett M"))
.map(student -> student.getChoices())
.findFirst()
.get();
In the first step, convert your students list to a Java 8 Stream.
Remember Stream is an abstraction:
students.stream()
Next, filter out that one particular student in which you are
interested in:
filter(student -> student.getName().equals("Garrett M"))
At this point, the Stream contains that one student which was
filtered. But we are interested in the choices that this student
has. Hence, convert this stream of Student to a stream of
choices:
.map(student -> student.getChoices())
Now that you have your choices, you can perform your desired
operations on them. That's it!! Done!!
findFirst().get();
This will give you a List<Integer>. Later you can convert this collection to an Integer array as:
Integer[] myChoices = myChoicesList.toArray(new Integer[myChoicesList.size()]);
Note: I've designed this snippet assuming that, getChoices() method from Student class returns a List<Integer> containing choices of that Student.

Related

How to find three consecutive rows with the for a given Id from a collection with some of the attributes same ? Java Stream

I have a scenario where I am reading from a csv file and loading into a List collection. The items are as below.
index name val1 val2 state note
1 xxx 12.43 13.56 1 1
2 xxx 12.43 13.56 0 0
3 xxx 12.43 13.56 0 0
4 yyy 5.9 13 1 1
5 zzz 5.4 5 0 1
6 ddd 6.8 7.78 1 1
7 ddd 6 1 1 0
8 xxx 12.43 13.56 1 1
9 zzz 1 1.56 1 1
10 ppp 1 0 0 0
11 yyy 1 1 1 0
12 ggg 1 1 1 1
13 ddd 1 1 0 0
14 www 0 0 0 0
15 www 1 0 0 0
Question 1 : I am trying to find three consecutive entries for a given item-name where the details of val1 and val2 haven't changed. If the values of these two fields haven't changed where they are non consecutive then it will still be fine (still count as consecutive).
How can i do using stream and get the number of consecutive entries with these three values ( name, val1 and val2) remaining same ?
Question 2: How can get a similar count for items which dont have three consecutive entries using stream for a given name?
I have tried doing something like this so far..
Map<String,Map<String,Map<String,Long>>> counting = list.stream()
.filter(p -> p.getName().equals(name))
.collect(Collectors.groupingBy(Item::getName,
Collectors.groupingBy(Item::getVal1,
Collectors.groupingBy(Item::getVal2, Collectors.counting()))));
Edit : streams or no streams how can I do this ?
The phrase "three consecutive entries" indicated that it is unlikely that a straight stream solution is appropriate: streams are designed for operations on independent items.
Given you are only looking at items with the same name the first step is to group by name. You can use streams to do this with something like: list.stream().collect(Collectors.groupingBy(Item::getName)).
The for each list of items (i.e. the values in the generated map), you can use logic like the following:
int currentRun = 0;
for (int i = 1; i < list.size(); i++) {
if (valuesMatch(list.get(i), list.get(i - 1))
currentRun++;
else
currentRun = 0;
if (currentRun > 3)
...
}
Following code snippet will give a Map of the Items for a given item name whose val1 and val2 are equal. And the map will be grouped by val1 (or val2, doesn't matter as val1 and val2 will be same). And for your second issue, you can just append an '!' before p.getName().equals(name), like !p.getName().equals(name) . You have to check the size of the list of the items against the key though.
Map<Long, List<Item>> itemsMap = list.stream()
.filter(p -> p.getName().equals(name) && p.getVal1().longValue()==p.getVal2().longValue())
.collect(Collectors.groupingBy(Item::getVal1));

How can I optimize my code for Swapping the array elements of given range of indexes with related element?

Consider an array of integers A having N elements in which each element has a one- to-one relation with another array element.
For each i, where 1≤i≤N there exists a 1−>1 relation between element i and element N−i+1
The Task is to perform following operations on this array which are as follows:
Given two integers (L,R) we have to swap each element in that range with its related element.(See Sample explanation below)
Sample Input
5
1 2 3 4 5
2
1 2
2 3
Sample Output
5 2 3 4 1
Explanation
For first query,we will swap 1 with 5 and 2 with 4.
Now the array becomes- 5 4 3 2 1
Similarly now ,for the second query we will swap 4 with 2 and 3 with itself.
So the final array will be 5 2 3 4 1
My Program goes like this:
import java.util.Scanner;
public class ProfessorAndOps {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in=new Scanner(System.in);
int n=in.nextInt();//length of array
int a[]=new int[n];//array declaration
for(int i=0;i<n;i++){
//inputting array elements
a[i]=in.nextInt();
}
int q=in.nextInt();//number of queries
for(int i=0;i<q;i++){
int l=in.nextInt();//left limit
int r=in.nextInt();//right limit
//swapping while iterating over the given range of array elements:
for(int j=l-1;j<=r-1;j++){
int temp=a[j];
a[j]=a[n-j-1];
a[n-j-1]=temp;
}
}
//Printing the output array:
for(int i=0;i<n;i++){
if(i!=n-1){
System.out.print(a[i]+" ");
}
else{
System.out.println(a[i]);
}
}
}
}
I could only come up with BruteForce solution. I'm pretty sure there will be some pre-processing step or some optimisation technique with l and r variables, whatever I could think of, giving me wrong answer. Please help me optimise this code. To be specific, I would need my code's time complexity to be reduced from O(N+ Q*(R-L)) to something like O(Q+N)
Here's an O(Q + N) time, O(N) space algorithm. Imagine a list of the corresponding swap counts only for L and R over the elements (we'll use a negative number for the R counts). What if we maintained a virtual stack while traversing it? (By "virtual," I mean it's not a real stack, just an integer that bears some theoretical similarity.)
For example:
1 2 3 4 5 6 7 8 9 10
O(Q) processing:
q [1,3]
1 9 8 7 5 ... <- what would happen to the array
0 1 0 -1 0 <- counts (what we actually store)
q [2,4]
1 9 3 4 6 ... <- what would happen to the array
0 1 1 -1 -1 <- counts (what we actually store)
O(N) traversal:
index 0 didn't move, no change, stack: 0
index 1 moved once, odd count, changed, stack: 1
index 2 moved 2 (stack + 1), even count, no change, stack: 2
index 3 moved 2 (stack), even count, no change, stack: 2 - 1
index 4 moved 1 (stack), odd count, changed, stack: 1 - 1

java write to file with paralellism, save order

I have a code which produces result in a loop in simmilar fashion:
//loop to write header for b (0-5)
(for int a = 0; a <5 ;a++){
//System.out.print(a + "| ");
IntStream.range(b = 0, 5 ).parallel().forEach(b -> {
int result = a*b;
//System.out.print(result + " ");
});
System.out.println("");
)
This was my attempt. The commented system outs basically done what i needed, except as parallel take's stuff in whatever order, my lines got mixed. How can I make sure, to get something like this? Instead of lines with random order of numbers in?
0 | 0 0 0 0 0
1 | 0 1 2 3 4
2 | 0 2 4 6 8
....
First of all, your problem is not one that is well-suited for parallelism. The overhead that parallelism provides far outweighs any savings you get by running your sums at the same time.
That said, you may want to consider using something like toArray to collapse your sums to an array, and then print each element in the array.

Duplicate for-loop practice, beginner needs advice to study

Understanding the -1 in the for loop, need detailed explanation with for and if lines of code included?
int[] array = { 2, 5, 1, 2, 3, 5 };
Arrays.sort(array);
// why does this start counting from 1, and if l put 0 it goes to error, out of bounds?
for (int i = 1; i < array.length; i++) {
if (array[i] == array[i - 1]) { // - 1?
System.out.print(array[i]);
}
}
There is nothing inherently wrong with it.
It just makes the iteration to start with i=1 up to the array's length, but since indexing in arrays are zero-based you have to offset it when getting the value.
That is why is array[i-1]
If you put i=0 then you also have to change the ending condition to array.length-1, and you have to access the values by array[i] in order to avoid going out of bounds.
For questions like this, take the code one line at a time and try to follow what it is doing.
The first thing you do here is to create an array, then sort it. After the Arrays.sort(array) call, your array will contain the following:
index 0 1 2 3 4 5
----------------------
contents 1 2 2 3 5 5
Remember, arrays are zero-indexed - that means the very first element is located at index 0. (The contents of the array don't matter, it's the index you want to pay attention to.)
Arrays cannot have indexes less then zero, and they also cannot have indexes greater than their length-1. So, for your example, that means you cannot use -1 as an index because it is less than 0. You also cannot use 6 as an index, since 6 is greater than the length of the array (6) minus one.
In the initialization of the for-loop, you set i equal to 1 for the first iteration. Though unconventional, it's perfectly legal. This simply represents which index we will start from in the array. So for the first iteration of the loop, array[i] will be pointing to the value 2, and array[i-1] points to the value 1.
index 0 1 2 3 4 5
----------------------
contents 1 2 2 3 5 5
i ^
i-1 ^
Now, what if you set i to start at index 0 instead? Well, then array[i] will point to the 0th index (value 1)... but what does array[i-1] point to?
index 0 1 2 3 4 5
----------------------
contents 1 2 2 3 5 5
i ^
i-1 ^
It's pointing to index -1. Since arrays can't have indexes of -1, this is causing your IndexOutOfBoundsException. Hopefully that makes sense.

In Java, how do I create a bitmap to solve "knapsack quandary"

I'm in my first programming course and I'm quite stuck right now. Basically, what we are doing is we take 16 values from a text file (on the first line of code) and there is a single value on the second line of code. We read those 16 values into an array, and we set that 2nd line value as our target. I had no problem with that part.
But, where I'm having trouble is creating a bitmap to test every possible subset of the 16 values, that equal the target number.
IE, say we had these numbers:
12 15 20 4 3 10 17 12 24 21 19 33 27 11 25 32
We then correspond each value to a bitmap
0 1 1 0 0 0 0 1 1 1 0 1 0 0 1 0
Then we only accept the values predicated with "1"
15 20 12 24 21 33 25
Then we test that subset to see if it equals the "target" number.
We are only allowed to use one array in the problem, and we aren't allowed to use the math class (haven't gotten to it yet).
I understand the concept, and I know that I need to implement shifting operators and the logical & sign, but I'm truly at a loss. I'm very frustrated, and I just was wondering if anybody could give me any tips.
To generate all possible bit patterns inside an int and thus all possible subsets defined by that bit map would simply require you to start your int at 1 and keep incrementing it to the highest possible value an unsigned short int can hold (all 1s). At the end of each inner loop, compare the sum to the target. If it matches, you got a solution subset - print it out. If not, try the next subset.
Can someone help to explain how to go about doing this? I understand the concept but lack the knowledge of how to implement it.
OK, so you are allowed one array. Presumably, that array holds the first set of data.
So your approach needs to not have any additional arrays.
The bit-vector is simply a mental model construct in this case. The idea is this: if you try every possible combination (note, NOT permutation), then you are going to find the closest sum to your target. So lets say you have N numbers. That means you have 2^N possible combinations.
The bit-vector approach is to number each combination with 0 to 2^N - 1, and try each one.
Assuming you have less that 32 numbers in the array, you essentially have an outer loop like this:
int numberOfCombinations = (1 << numbers.length - 1) - 1;
for (int i = 0; i < numberOfCombinations; ++i) { ... }
for each value of i, you need to go over each number in numbers, deciding to add or skip based on shifts and bitmasks of i.
So the task is to what an algorithm that, given a set A of non-negative numbers and a goal value k, determines whether there is a subset of A such that the sum of its elements is k.
I'd approach this using induction over A, keeping track of which numbers <= k are sums of a subset of the set of elements processed so far. That is:
boolean[] reachable = new boolean[k+1];
reachable[0] = true;
for (int a : A) {
// compute the new reachable
// hint: what's the relationship between subsets of S and S \/ {a} ?
}
return reachable[k];
A bitmap is, mathematically speaking, a function mapping a range of numbers onto {0, 1}. A boolean[] maps array indices to booleans. So one could call a boolean[] a bitmap.
One disadvanatage of using a boolean[] is that you must process each array element individually. Instead, one could use that a long holds 64 bits, and use bitshifting and masking operations to process 64 "array" elements at a time. But that sort of microoptimization is error-prone and rather involved, so not commonly done in code that should be reliable and maintainable.
I think you need something like this:
public boolean equalsTarget( int bitmap, int [] numbers, int target ) {
int sum = 0; // this is the variable we're storing the running sum of our numbers
int mask = 1; // this is the bitmask that we're using to query the bitmap
for( int i = 0; i < numbers.length; i++ ) { // for each number in our array
if( bitmap & mask > 0 ) { // test if the ith bit is 1
sum += numbers[ i ]; // and add the ith number to the sum if it is
}
mask <<= 1; // shift the mask bit left by 1
}
return sum == target; //if the sum equals the target, this bitmap is a match
}
The rest of your code is fairly simple, you just feed every possible value of your bitmap (1..65535) into this method and act on the result.
P.s.: Please make sure that you fully understand the solution and not just copy it, otherwise you're just cheating yourself. :)
P.p.s: Using int works in this case, as int is 32 bit wide and we only need 16. Be careful with bitwise operations though if you need all the bits, as all primitive integer types (byte, short, int, long) are signed in Java.
There are a couple steps in solving this. First you need to enumerate all the possible bit maps. As others have pointed out you can do this easily by incrementing an integer from 0 to 2^n - 1.
Once you have that, you can iterate over all the possible bit maps you just need a way to take that bit map and "apply" it to an array to generate the sum of the elements at all indexes represented by the map. The following method is an example of how to do that:
private static int bitmapSum(int[] input, int bitmap) {
// a variable for holding the running total
int sum = 0;
// iterate over each element in our array
// adding only the values specified by the bitmap
for (int i = 0; i < input.length; i++) {
int mask = 1 << i;
if ((bitmap & mask) != 0) {
// If the index is part of the bitmap, add it to the total;
sum += input[i];
}
}
return sum;
}
This function will take an integer array and a bit map (represented as an integer) and return the sum of all the elements in the array whose index are present in the mask.
The key to this function is the ability to determine if a given index is in fact in the bit map. That is accomplished by first creating a bit mask for the desired index and then applying that mask to the bit map to test if that value is set.
Basically we want to build an integer where only one bit is set and all the others are zero. We can then bitwise AND that mask with the bit map and test if a particular position is set by comparing the result to 0.
Lets say we have an 8-bit map like the following:
map: 1 0 0 1 1 1 0 1
---------------
indexes: 7 6 5 4 3 2 1 0
To test the value for index 4 we would need a bit mask that looks like the following:
mask: 0 0 0 1 0 0 0 0
---------------
indexes: 7 6 5 4 3 2 1 0
To build the mask we simply start with 1 and shift it by N:
1: 0 0 0 0 0 0 0 1
shift by 1: 0 0 0 0 0 0 1 0
shift by 2: 0 0 0 0 0 1 0 0
shift by 3: 0 0 0 0 1 0 0 0
shift by 4: 0 0 0 1 0 0 0 0
Once we have this we can apply the mask to the map and see if the value is set:
map: 1 0 0 1 1 1 0 1
mask: 0 0 0 1 0 0 0 0
---------------
result of AND: 0 0 0 1 0 0 0 0
Since the result is != 0 we can tell that index 4 is included in the map.

Categories