I am trying to read specific elements within lines of an ArrayList. For example, an array list called Combinations of size 3 with the following lines is being produced by my code:
Combinations =
[0, 1]
[0, 2]
[1, 2]
I would like to create a loop that will read each line of the array, each element of that line, and add strings to a new array depending on the values of that array line. What should I use in order to accomplish the following pseudocode in java?
Pseudocode would be as follows
For (int i = 0; i < Combinations.size(); i++)
If Combinations(Line i, First Element) = "0"
Then NewArray(i).add("Vial1,")
If Combinations(Line i, First Element) = "1"
Then NewArray(i).add("Vial2,")
If Combinations(Line i, First Element) = "2"
Then NewArray(i).add("Vial3,")
If Combinations(Line i, Second Element)= "0"
Then NewArray(i).add(+"Vial1")
If Combinations(Line i, Second Element)= "1"
Then NewArray(i).add(+"Vial2")
If Combinations(Line i, Second Element)= "2"
Then NewArray(i).add(+"Vial3")
The resulting ArrayList would then be:
NewArray =
[Vial1,Vial2]
[Vial1,Vial3]
[Vial2,Vial3]
Below is the code which I am using to generate my Arraylist
import java.util.*;
import org.apache.commons.math3.util.CombinatoricsUtils;
public class Combinations1 {
public static void main (String[] args){
ArrayList<Integer[]> combinations = new ArrayList();
Iterator<int[]> iter = CombinatoricsUtils.combinationsIterator(3, 2);
while (iter.hasNext()) {
int[] resultint = iter.next();
Integer[] resultInteger = new Integer[2];
for (int i = 0; i < 2; i++) {
resultInteger[i] = Integer.valueOf(resultint[i]);
}
combinations.add(resultInteger);
}
for (int i = 0; i < combinations.size(); i++) {
System.out.println(Arrays.deepToString(combinations.get(i)));
}}}
Your pseudocode is a bit of a mess. You seem to be wanting to turn what is currently an array of Integers into an array of Strings.
I think you want something like this:
ArrayList<String[]> NewArray = new ArrayList<String[]>();
for (Integer[] combination : combinations) {
String[] newCombination = new String[2];
if (combination[0].intValue() == 0) {
newCombination[0] = "Vial1";
}
... etc for other possible values
if (combination[1].intValue() == 0) {
newCombination[1] = "Vial1";
}
.. etc for other values
NewArray.add(newCombination);
}
Of course if your rule is exactly 0 -> Vial1, 1 -> Vial2 etc, you don't need to handle each case separately, but instead:
newCombination[0] = "Vial" + (combination[0].intValue() + 1);
and the same for the second element. If the rule is the same for both you could just iterate over the elements of the array too. Hopefully you can figure that out for yourself.
Do you mean something like this?
String[][] newArray = new String[combinations.size()][2];
for (int i = 0; i < combinations.size(); i++) {
Integer[] eachArray = combinations.get(i);
for (int j = 0; j < eachArray.length; j++){
int elem = eachArray[j];
if (elem==0 || elem==1 || elem==2){
newArray[i][j]="Vial"+(elem+1);
}
}
}
Related
Currently working on a method that takes a n*n matrix as input and returns an array consisting of all elements that are found in each sub-array. However, since I need it to also include duplicates etc, it's harder than I thought.
Googled the hell out of it, however, yet to find a solution which matches my criteria of repetition.
Currently I have this, which compares the element's of the first row with every other row and all their elements. If the counter gets to the length where it confirms that the element indeed is present in all rows, it adds it to the array. However, this has faults in it. First of all, since I create a set array in the beginning with the maximum possible length, it might return an array with non-needed 0's in it. And second, the duplicate part is not working correctly, struggling to implement a check there.
Examples of input/output that I need:
Input matrix: {{2,2,1,4},{4,1,2,2},{7,1,2,2},{2,10,2,1}}
Desired output: {1, 2, 2}
My output: {2, 2, 1, 0}
Input matrix: {{2,2,1,4},{4,1,3,2},{7,1,9,2},{2,10,2,1}}
Desired output: {1, 2}
My output: {2, 2, 1, 0}
public static int[] common_elements(int[][] matrix){
int[] final_array = new int[matrix.length];
for (int i = 0; i < matrix.length; i++) {
int counter = 0;
for (int j = 1; j < matrix.length; j++) {
for (int k = 0; k < matrix.length; k++) {
if(matrix.[0][i] == matrix.[j][k]){
counter += 1;
break;
}
}
}
if(counter == a.length-1){
final_array[i] = a[0][i];
}
}
return final_array;
}
EDIT: This is what I finally got together that fits my requirements and works flawlessly, with comments
public static int[] repetitiveInts(int[][] a){
//This is a method declared outside for sorting every row of the matrix ascending-ly before I do the element search.
for (int i = 0; i < a.length; i++) {
sorting(a[i]);
}
//Declaring a LinkedList in order to add elements on the go
LinkedList<Integer> final_list= new LinkedList<Integer>();
//Iterating through the matrix with every element of the first row, counting if it appears in every row besides the first one.
for (int i = 0; i < a.length; i++) {
int counter = 0;
for (int j = 1; j < a.length; j++) {
for (int k = 0; k < a.length; k++) {
//Checking if an element from the other rows match
if(a[0][i] == a[j][k]){
a[j][k] = a[0][i]-1; //If a match is found, the element is changed so finding duplicates is possible.
counter += 1;
break; //Breaking and checking the next row after one row checks out successfully.
}
}
}
//If the element is indeed in every row, adds it to the lit.
if(counter == a.length-1){
final_list.add(a[0][i]);
}
}
//Since I had to return a regular int[] array, converting the LinkedList into an array.
int[] final_realarray= new int[final_list.size()];
for (int i = 0; i < final_list.size(); i++) {
final_realarray[i] = final_list.get(i);
}
return final_realarray;
Grateful for help :)
The most efficient way to solve this problem is by creating a histogram of frequencies for each nested array in the matrix (i.e. determine the number of occurrences for every element in the nested array).
Every histogram will be represented by a Map<Integer, Integer> (array element as a key, its occurrences as a value). To generate a histogram only a single pass through the array is needed. In the solution below this logic resides inside the getFrequencies() method.
After creating all histograms we have to merge them. In terms of set theory we are looking for an intersection of keys in all histograms. I.e. we need only those keys that appear at least once in every histogram and a value for each key will be the smallest in all histograms for that key. This logic is placed in the getCommonElements().
In order to create a merged histogram, we can pick any of the histograms (in the code below the first histogram is used frequencies.get(0).keySet()) and iterate over its keys. Then in the nested loop, for every key, we need to find the minimum value associated with that in every histogram in a list (reminder: that will be the smallest number of occurrences for the key).
At the same time, while merging histograms we can also find the length of the resulting array by adding all the minimal frequencies together. That small optimization will allow to avoid doing the second iteration over the merged map.
The last step required is to populate the resulting array commonElements with keys from the merged histogram. Value of every key denotes how many times it has to be placed in the resulting array.
public static void main(String[] args) {
System.out.println(Arrays.toString(commonElements(new int[][]{{2,2,1,4},{4,1,2,2},{7,1,2,2},{2,10,2,1}})));
System.out.println(Arrays.toString(commonElements(new int[][]{{2,2,1,4},{4,1,3,2},{7,1,9,2},{2,10,2,1}})));
}
public static int[] commonElements(int[][] matrix){
List<Map<Integer, Integer>> frequencies = getFrequencies(matrix);
return getCommonElements(frequencies);
}
private static List<Map<Integer, Integer>> getFrequencies(int[][] matrix) {
List<Map<Integer, Integer>> frequencies = new ArrayList<>();
for (int[] arr: matrix) {
Map<Integer, Integer> hist = new HashMap<>(); // a histogram of frequencies for a particular array
for (int next: arr) {
// hist.merge(next, 1, Integer::sum); Java 8 alternative to if-else below
if (hist.containsKey(next)) {
hist.put(next, hist.get(next) + 1);
} else {
hist.put(next, 1);
}
}
frequencies.add(hist);
}
return frequencies;
}
private static int[] getCommonElements(List<Map<Integer, Integer>> frequencies) {
if (frequencies.isEmpty()) { // return an empty array in case if no common elements were found
return new int[0];
}
Map<Integer, Integer> intersection = new HashMap<>();
int length = 0;
for (Integer key: frequencies.get(0).keySet()) { //
int minCount = frequencies.get(0).get(key); // min number of occurrences of the key in all maps
for (Map<Integer, Integer> map: frequencies) {
int nextCount = map.getOrDefault(key, 0);
minCount = Math.min(nextCount, minCount); // getOrDefault is used because key might not be present
if (nextCount == 0) { // this key isn't present in one of the maps, no need to check others
break;
}
}
if (minCount > 0) {
intersection.put(key, minCount);
length += minCount;
}
}
int[] commonElements = new int[length];
int ind = 0;
for (int key: intersection.keySet()) {
int occurrences = intersection.get(key);
for (int i = 0; i < occurrences; i++) {
commonElements[ind] = key;
ind++;
}
}
return commonElements;
}
output
[1, 2, 2]
[1, 2]
Side note: don't violate the naming conventions, use camel-case for method and variable names.
Update
I've managed to implement a brute-force solution based on arrays and lists only as required.
The most important thing is that for this task you need two lists: one to store elements, another to store frequencies. Lists are bound together via indices. And these two lists are basically mimic a map, frankly saying a very inefficient one (but that's a requirement). Another possibility is to implement a class with two int fields that will represent the data for a common element, and then store the instances of this class in a single list. But in this case, the process of checking whether a particular element already exists in the list will be much more verbose.
The overall logic has some similarities with the solution above.
First, we need to pick a single array in the matrix (matrix[0]) and compare all its unique elements against the contents of all other arrays. Every element with non-zero frequency will be reflected in the list of elements and in the list of frequencies at the same index in both. And when the resulting array is being created the code relies on the corresponding indices in these lists.
public static int[] commonElements(int[][] matrix){
if (matrix.length == 0) { // case when matrix is empty - this condition is required because farther steps will lead to IndexOutOfBoundsException
return new int[0];
}
if (matrix.length == 1) { // a small optimization
return matrix[0];
}
// Map<Integer, Integer> frequencyByElement = new HashMap<>(); // to lists will be used instead of Map, because of specific requirement for this task
List<Integer> frequencies = new ArrayList<>(); // lists will be bind together by index
List<Integer> elements = new ArrayList<>();
int length = 0; // length of the resulting array
for (int i = 0; i < matrix[0].length; i++) {
if (elements.contains(matrix[0][i])) { // that means this element is a duplicate, no need to double-count it
continue;
}
int currentElement = matrix[0][i];
int minElementCount = matrix[0].length; // min number of occurrences - initialized to the max possible number of occurrences for the current array
// iterating over the all nested arrays in matrix
for (int row = 0; row < matrix.length; row++) {
int localCount = 0; // frequency
for (int col = 0; col < matrix[row].length; col++) {
if(matrix[row][col] == currentElement){
localCount++;
}
}
if (localCount == 0) { // element is absent in this array and therefore has to be discarded
minElementCount = 0;
break; // no need to iterate any farther, breaking the nested loop
}
minElementCount = Math.min(localCount, minElementCount); // adjusting the value the min count
}
// frequencyByElement.put(currentElement, minElementCount); // now we are sure that element is present in all nested arrays
frequencies.add(minElementCount);
elements.add(currentElement);
length += minElementCount; // incrementing length
}
return getFinalArray(frequencies, elements, length);
}
private static int[] getFinalArray(List<Integer> frequencies,
List<Integer> elements,
int length) {
int[] finalArray = new int[length];
int idx = 0; // array index
for (int i = 0; i < elements.size(); i++) {
int element = elements.get(i);
int elementCount = frequencies.get(i);
for (int j = 0; j < elementCount; j++) {
finalArray[idx] = element;
idx++;
}
}
return finalArray;
}
I want the numbers in the first array that do not repeat with the numbers in the second array to go to the third array
This is what I have done till now and it doesn`t work...please help
for(int i = 0; i < isir.length; i++)
{
for(int j = 0 ; j < isir2.length; j++)
{
if(isir[i] != isir[j])
{
for(int k = 0; k < sirdif1.length; k++)
{
sirdif1[k] = isir[i];
}
}
}
}
I am entering the numbers from console with Scanner function...
With using lists and steams:
Integer a1[] = {1,2,5,6,8};
Integer a2[] = {1,3,5,7,8};
List<Integer> result = new ArrayList<>();
// Add elements from first array which ist not in the second
Arrays.stream(a1).filter(_a -> !Arrays.asList(a2).contains(_a)).forEach(result::add);
// Add elements from second array which ist not in the first
Arrays.stream(a2).filter(_a -> !Arrays.asList(a1).contains(_a)).forEach(result::add);
result.forEach(System.out::println);
Output will be:
2
6
3
7
I'd probably use Sets for clarity.
public void test() {
Integer[] a1 = {1,2,3,4,5};
Integer[] a2 = {2,3,4};
// Treat them as Sets.
Set<Integer> s1 = new HashSet<>(Arrays.asList(a1));
Set<Integer> s2 = new HashSet<>(Arrays.asList(a2));
// Get the union of both.
Set<Integer> all = new HashSet<>(s1);
all.addAll(s2);
// Find the repeating ones.
Set<Integer> common = new HashSet<>(s1);
common.retainAll(s2);
// Non-repeating is.
Set<Integer> nonRepeats = new HashSet<>(all);
nonRepeats.removeAll(common);
System.out.println(nonRepeats);
}
I would suggest good naming conventions first..variables like sirdif1(i cant even imagine how this name was decided..) really make it hard for others to read/help
int a1[] ; // Initialize array1
int a2[] ; // Initialize array2
List<Integer> tempList = new ArrayList<Integer>();
for(int i = 0; i < a2.length; i++)
{
boolean found = false; // To be able to track if the int was found in both arrays
for(int j = 0; j < a1.length; j++)
{
if(a1[j].equals(a2[i]))
{
found = true;
break; // If it exist in both arrays there is no need to look further
}
}
if(!found ) // If the same is not found in both..
tempList.add(a2[i]); // .. add to temporary list
}
//Temporary array to combine both arrays;
int[] merged= new int[isir1.length + isir1.length];
//Copy isir1 into new temporary "merged" array;
System.arraycopy(isir1, 0, merged, 0, isir1.length);
//Copy isir2 into new temporary "merged" array;
System.arraycopy(isir2, 0, merged, isir1.length, isir2.length);
//Get the unique values of array "merged" and assign them to new array;
int[] sirdif1= IntStream.of(merged).distinct().toArray();
I found this code online and it works well to permute through the given array and return all possible combinations of the numbers given. Does anyone know how to change this code to incorporate a 2D array instead?
public static ArrayList<ArrayList<Integer>> permute(int[] numbers) {
ArrayList<ArrayList<Integer>> permutations = new ArrayList<ArrayList<Integer>>();
permutations.add(new ArrayList<Integer>());
for ( int i = 0; i < numbers.length; i++ ) {
ArrayList<ArrayList<Integer>> current = new ArrayList<ArrayList<Integer>>();
for ( ArrayList<Integer> p : permutations ) {
for ( int j = 0, n = p.size() + 1; j < n; j++ ) {
ArrayList<Integer> temp = new ArrayList<Integer>(p);
temp.add(j, numbers[i]);
current.add(temp);
}
}
permutations = new ArrayList<ArrayList<Integer>>(current);
}
return permutations;
}
This is what I have attempted:
public static int[][] permute(int[] numbers){
int[][] permutations = new int[24][4];
permutations[0] = new int[4];
for ( int i = 0; i < numbers.length; i++ ) {
int[][] current = new int[24][4];
for ( int[] permutation : permutations ) {
for ( int j = 0; j < permutation.length; j++ ) {
permutation[j] = numbers[i];
int[] temp = new int[4];
current[i] = temp;
}
}
permutations = current;
}
return permutations;
}
However this returns all zeroes. I chose 24 and 4 because that is the size of the 2D array that I need.
Thanks
It’s not really that easy. The original code exploits the more dynamic behaviour of ArrayList, so a bit of hand coding will be necessary. There are many correct thoughts in your code. I tried to write an explanation of the issues I saw, but it became too long, so I decided to modify your code instead.
The original temp.add(j, numbers[i]); is the hardest part to do with arrays since it invloves pushing the elements to the right of position j one position to the right. In my version I create a temp array just once in the middle loop and shuffle one element at a time in the innermost loop.
public static int[][] permute(int[] numbers) {
// Follow the original here and create an array of just 1 array of length 0
int[][] permutations = new int[1][0];
for (int i = 0; i < numbers.length; i++) {
// insert numbers[i] into each possible position in each array already in permutations.
// create array with enough room: when before we had permutations.length arrays, we will now need:
int[][] current = new int[(permutations[0].length + 1) * permutations.length][];
int count = 0; // number of new permutations in current
for (int[] permutation : permutations) {
// insert numbers[i] into each of the permutation.length + 1 possible positions of permutation.
// to avoid too much shuffling, create a temp array
// and use it for all new permutations made from permutation.
int[] temp = Arrays.copyOf(permutation, permutation.length + 1);
for (int j = permutation.length; j > 0; j--) {
temp[j] = numbers[i];
// remember to make a copy of the temp array
current[count] = temp.clone();
count++;
// move element to make room for numbers[i] at next position to the left
temp[j] = temp[j - 1];
}
temp[0] = numbers[i];
current[count] = temp.clone();
count++;
}
assert count == current.length : "" + count + " != " + current.length;
permutations = current;
}
return permutations;
}
My trick with the temp array means I don’t get the permutations in the same order as in the origianl code. If this is a requirement, you may copy permutation into temp starting at index 1 and shuffle the opposite way in the loop. System.arraycopy() may do the initial copying.
The problem here is that you really need to implement properly the array version of the ArrayList.add(int,value) command. Which is to say you do an System.arraycopy() and push all the values after j, down one and then insert the value at j. You currently set the value. But, that overwrites the value of permutation[j], which should actually have been moved to permutations[j+1] already.
So where you do:
permutation[j] = numbers[i];
It should be:
System.arraycopy(permutation,j, permutations, j+1, permutations.length -j);
permutation[j] = numbers[i];
As the ArrayList.add(int,value) does that. You basically wrongly implemented it as .set().
Though personally I would scrap the code and go with something to dynamically make those values on the fly. A few more values and you're talking something prohibitive with regard to memory. It isn't hard to find the nth index of a permutation. Even without allocating any memory at all. (though you need a copy of the array if you're going to fiddle with such things without incurring oddities).
public static int[] permute(int[] values, long index) {
int[] returnvalues = Arrays.copyOf(values,values.length);
if (permutation(returnvalues, index)) return returnvalues;
else return null;
}
public static boolean permutation(int[] values, long index) {
return permutation(values, values.length, index);
}
private static boolean permutation(int[] values, int n, long index) {
if ((index == 0) || (n == 0)) return (index == 0);
int v = n-(int)(index % n);
int temp = values[n];
values[n] = values[v];
values[v] = temp;
return permutation(values,n-1,index/n);
}
I have any amount of arrays of integers like:
[1,9]
[5]
[7]
And I want to combine them in such a way that I get sets of numbers like:
[1,5,7]
[9,5,7]
Another Example INPUT:
[1,9]
[3,5]
[7]
[10]
OUTPUT:
[1,3,7,10]
[9,3,7,10]
[1,5,7,10]
[9,5,7,10]
I have tried nesting "for" loops but I always seem to get lost and can't get the right iterators I need to pull the right numbers when building the final array. There can be any number of integers in each array, and any number of arrays.
I have tried something like this, but it seems like a deadend:
int[][] allIndexes = {{1, 9},{5},{7}};
List<Integer> dataset1 = new ArrayList<Integer>();
//int[] dataset2 = {};
int i = 0;
for (int[] indexSet : allIndexes){
if(indexSet.length > i){
dataset1.add(indexSet[i]);
}else{
dataset1.add(indexSet[0]);
}
i++;
}
System.out.println(dataset1.toString());
//System.out.println(dataset2);
Any help would be greatly appreciated. I tried searching for others, but I really am not sure if I am defining this correctly.
You need a variable number of nested loops to enumerate all cases. Thus, recursion is your friend here. The code below will do what you're asking.
public static void main(String[] args)
{
int[][] allIndexes = {{1, 9},{3,5},{7},{10}};
List<Integer> dataset1;
if( allIndexes.length > 0)
{
int[] firstIndexes = allIndexes[0];
for( int i = 0; i < firstIndexes.length; i++)
{
dataset1 = new ArrayList<Integer>();
dataset1.add( firstIndexes[i]);
foo( dataset1, allIndexes, 1);
}
}
}
public static void foo( List<Integer> dataset1, int[][] allIndexes, int index)
{
if( index < allIndexes.length)
{
int[] indexes = allIndexes[index];
for( int i = 0; i < indexes.length; i++)
{
List<Integer> dataset = new ArrayList<Integer>();
for( Integer integer : dataset1)
dataset.add( integer);
dataset.add( indexes[i]);
foo( dataset, allIndexes, index+1);
}
}
else
{
StringBuilder sb = new StringBuilder();
sb.append( "[");
for( int i = 0; i < dataset1.size() - 1; i++)
sb.append( dataset1.get( i) + ",");
sb.append( dataset1.get( dataset1.size()-1));
sb.append( "]");
System.out.println( sb.toString());
}
}
Edit seems uoyilmaz was faster with his answer
Edit2 fixed a typo
I think a recursive approach might be worth a try.
You have your first input array and all following input arrays.
You want to get all combinations of your following input arrays and combine each of them with every element from your first input array
[1,9] // first input array
[5] // following input arrays
[7] // following input arrays
.
void GetCombinations(int[][] arrays, int startIndex, LinkedList<LinkedList<Integer>> outLists) {
// startIndex to high
if (startIndex >= arrays.length) return;
int[] firstArray = arrays[startIndex]
LinkedList<LinkedList<Integer>> subLists = new LinkedList<LinkedList<Integer>>();
// get sub-results
GetCombinations(arrays, startIndex + 1, subLists);
// combine with firstArray
if (subLists.size() == 0) {
subLists.add(new LinkedList<Integer>());
}
for (int i = 0; i < subLists.size(); ++i) {
for (int j = 0; j < firstArray.length; ++j) {
LinkedList<Integer> temp = new LinkedList<Integer>(subLists.get(i));
temp.addFirst(firstArray[j]);
outLists.add(temp);
}
}
}
You then call the function with
int[][] yourInputArrays = { ... };
LinkedList<LinkedList<Integer>> outputLists = new LinkedList<LinkedList<Integer>>();
GetCombinations(yourInputArrays, 0, outputLists);
If you are new to programming, the recursive approach might not be intuitive at first, but it is definitely worth looking into it.
Almost done making Powerball game, but theres a semantic error. Trying to compare two arrays of 5 ints and return number of matches. However if there is a duplicate number the number is matched multiple times. I need to delete both numbers after they are matched.
I tried using arraylist as suggested on here but arraylist is "Unused import statement" and .remove is "cannot resolve method"
import java.util.ArrayList;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (balls[i] == yballs[j]) {
match++;
balls.remove();
remove(yballs, yballs[j]);
}
}
}
public static int[] remove(int[] symbols, int c) {
for (int i = 0; i < symbols.length; i++) {
if (symbols[i] == c) {
int[] copy = new int[symbols.length-1];
System.arraycopy(symbols, 0, copy, 0, i);
System.arraycopy(symbols, i+1, copy, i, symbols.length-i-1);
return copy;
}
}
return symbols;
}
As a solution to use ArrayList
You could populate the 2 ArrayLists to represent the two collection of balls and the one to hold the matches:
List<Integer> balls = new ArrayList<Integer>();
List<Integer> yballs = new ArrayList<Integer>();
List<Integer> matches = new ArrayList<Integer>();
balls.add(<ball number>);
...
yballs.add(<ball number>);
...
Then you would go through each ArrayList as:
for (Integer ballNumber : balls) {
for (Integer yballNumber : yballs) {
if (ballNumber == yballNumber) {
matches.add(ballNumber);
}
}
}
And to remove all the duplicates from both Lists:
balls.removeAll(matches);
yballs.removeAll(matches);
If you don't want to remove all of them and just remove one of the duplicates, you can do:
for (Integer match : matches) {
balls.remove(match);
yballs.remove(match);
}