So the problem I'm working on solving involves an array list of array list of integers
. What is known: The number of elements in each ArrayList of integers. What is NOT known: How many ArrayList of Integers there actually are. I need suggestions for an algorithm that would sum the (ordered) elements of these arrays in every combination possible OF the arrays. In order to clarify what I mean by this let me give an example:
AoA = [[1,0,1,0],[0,1,0,1],[1,1,1,1],[0,0,0,0]];
Sum the elements of AoA[0] + AoA[1]; AoA[0]+AoA[2]; AoA[0]+AoA[3]; AoA[1]+AoA[2]; AoA[1]+AoA[3]; AoA[2]+AoA[3];
(4 choose 2)
So if anyone could code this simple version I'd be grateful as I'm struggling to do it. If anyone could code the more complex example where there's an unknown number of arrays in the AoA (so N choose 2), you'd be my hero.
TL;DR/edit
I need an algorithm to take n-choose-2 arrays from an array of arrays; sum the arrays (e.g. [1,2,3] + [1,2,3] = [2,4,6]); put the add the new summed array into an array of arrays.
If the 2 is fixed then the easiest thing I can think about is just generating the new array with N*(N-1)/2 rows, one for each sum and then using two variables to iterate through the original array with something like:s
int c = 0;
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
for (int k = 0; k < M; k++) {
sums[c][k] = AoA[i][k] + AoA[j][k];
}
c++;
}
}
Here's what I've got, took me a while but this will do what I was looking for:
it takes each combination of the arrays (t1, t2, t3, t4) and adds their elements and returns whatever combinatorial you choose for n, (in this example i left it as 3).
If there's any more optimizations you can see please feel free to add it. I'm a perl guy so making this work at all in Java was a real task.
import java.util.ArrayList;
public class testnCk {
public static void main(String[] args) {
ArrayList<int[]> sums = new ArrayList<int[]>();
int [] t1 = {1,1,0,0};
int [] t2 = {1,0,0,1};
int [] t3 = {0,0,0,0};
int [] t4 = {0,0,1,1};
ArrayList<int[]> testing = new ArrayList<int[]>();
testing.add(t1);
testing.add(t2);
testing.add(t3);
testing.add(t4);
int n = 3;
int i = -1;
int[] array = new int[4];
ArrayList<int[]> whatever = nCk(testing, sums, array, i, n);
for (int[] test1 : whatever)
{
for (int j = 0; j < test1.length; j++) {
System.out.print(test1[j]);
}
System.out.println();
}
}
public static ArrayList<int[]> nCk (ArrayList<int[]> arrayOfDiffPatterns, ArrayList<int[]> solutions, int[] tempsums, int i, int n)
{
n--;
for (int j=i+1; j<arrayOfDiffPatterns.size(); j++){
int[] array = tempsums.clone();
for (int k=0; k<arrayOfDiffPatterns.get(0).length; k++){
array[k] += arrayOfDiffPatterns.get(j)[k];
}
if(n>0){
nCk(arrayOfDiffPatterns, solutions, array, j, n);
}
else{
solutions.add(array);
}
}
return solutions;
}
}
Related
How to sort 1D (String) array and 2D (int) array based on 1D (double) array with Bubble Sort in Java.
I managed to sort String array based on double array but can't figure out how to also sort 2D (int) array.
Every row in 2D array (grades) represents each students multiple grades.
I need to achieve goal by using this kind of structure (three arrays).
Everything needs to be sorted depending on finalGrade array.
static void sort(String[] students, int[][] grades, double[] finalGrade) {
double tempFG;
String tempStud;
int t;
//Bubble Sort
for (int i=0; i<students.length-1; i++) {
for (int j=0; j<finalGrade.length-i-1; j++) {
if (finalGrade[j] < finalGrade[j+1]) {
tempFG = finalGrade[j];
tempStud = students[j];
finalGrade[j] = finalGrade[j+1];
students[j] = students[j+1];
finalGrade[j+1] = tempFG;
students[j+1] = tempStud;
}
}
}
}
As was mentioned, sorting indices would be easier with fewer items to swap. But better would be to:
use a class (as also suggested).
implement a quick sort or equivalent (or use the ones in the API).
Here is some data. There is no relationship between grades and final grades.
String[] students = {"John", "May", "Helen", "Jim", "George"};
int[][] grades = {{88,97},{100,84},{80, 85},{92,91},{91,78}};
double[] finalGrade = {88.5, 92.6, 85.2, 89.3, 91.3};
Now sort and print
int indices[] = sort(students, grades, finalGrade);
for (int i = 0; i < indices.length; i++) {
int k = indices[i];
System.out.printf("%6s - %f - %s%n",students[k],
finalGrade[k], Arrays.toString(grades[k]));
}
prints
May - 92.600000 - [100, 84]
George - 91.300000 - [91, 78]
Jim - 89.300000 - [92, 91]
John - 88.500000 - [88, 97]
Helen - 85.200000 - [80, 85]
this method returns the indices for use in printing the results. If a class were used then the index sort wouldn't be required since. Then the list or array of objects could be returned.
initialize the index list from 0 to length of arrays.
this works the same way as any bubble or selection sort except that indices array is used to index into the finalGrade array and the indices are swapped based on the result of the comparison.
static int[] sort(String[] students, int[][] grades, double[] finalGrade) {
//Bubble Sort
int[] indices = new int[grades.length];
Arrays.setAll(indices, i->i);
for (int i=0; i<students.length-1; i++) {
for (int j=i+1; j<finalGrade.length; j++) {
if (finalGrade[indices[i]] < finalGrade[indices[j]]) {
int t = indices[j];
indices[j] = indices[i];
indices[i] = t;
}
}
}
return indices;
}
The above is actually a variation of a selection sort. Your loop parameters don't work and your implementation has other problems. You can still apply the above to a Bubble-sort
If you must do it in this manner then sorting the 2D array is no harder than sorting any other array. You have to remember that a 2D array is just an array of arrays. i.e just treat the inner array the way you would treat any other object in an array.
static void sort(String[] students, int[][] grades, double[] finalGrade) {
double tempFinalGrade;
String tempStudent; //I think using well descriptive vars is better
int [] tempGrade;
//Bubble Sort
for (int i=0; i<students.length-1; i++) {
for (int j=0; j<finalGrade.length-i-1; j++) {
if (finalGrade[j] < finalGrade[j+1]) {
tempFinalGrade = finalGrade[j];
tempStudent = students[j];
tempGrade = grades[j];//addition
finalGrade[j] = finalGrade[j+1];
students[j] = students[j+1];
grades[j] = grades[j+1]; //addition
finalGrade[j+1] = tempFinalGrade;
students[j+1] = tempStudent;
grades[j+1] = tempGrade; //addition
}
}
}
}
I will say that I think this is not a good way at all to solve this problem. abstracting this in a class would be much better.
As mentioned in the comments, the better, less cluttered way of sorting a 2D array would be to sort an array of indices numbered 0 to n-1, where n is the total number of items.
Then at the end, use the indices to point to, or even regenerate the 2D array.
static void sort(String[] students, int[][] grades, double[] finalGrade) {
int tempIndex;
int[] indices = new int[finalGrade.length];
for (int i = 0; i < finalGrade.length; ++i)
indices[i] = i;
//Bubble Sort
for (int i=0; i<students.length-1; i++) {
for (int j=0; j<finalGrade.length-i-1; j++) {
if (finalGrade[indices[j]] < finalGrade[indices[j+1]]) {
tempIndex = indices[j];
indices[j] = indices[j+1];
indices[j+1] = tempIndex;
}
}
}
// Output results
for (int i = 0; i < indices.length; ++i)
System.out.println(students[indices[i]] + " " + finalGrade[indices[i]]);
}
Note that you do not have to swap multiple arrays, as the index array points to the sorted item.
So, I am trying to create 2 randomly generated arrays,(a, and b, each with 10 unique whole numbers from 0 to 20), and then creating 2 arrays with the info of the last two. One containing the numbers that appear in both a and b, and another with the numbers that are unique to a and to b. The arrays must be listed in a "a -> [1, 2, 3,...]" format. At the moment I only know how to generate the 2 arrays, and am currently at the Intersection part. The problem is, that I can create a array with the correct list of numbers, but it will have the same length of the other two, and the spaces where it shouldn't have anything, it will be filled with 0s when its supposed to create a smaller array with only the right numbers.
package tps.tp1.pack2Arrays;
public class P02ArraysExtractUniqsAndReps {
public static void main(String[] args) {
int nbr = 10;
int min = 0;
int max = 20;
generateArray(nbr, min, max);
System.out.println();
}
public static int[] generateArray(int nbr, int min, int max) {
int[] a = new int[nbr];
int[] b = new int[nbr];
int[] s = new int[nbr];
s[0] = 0;
for (int i = 0; i < a.length; i++) {
a[i] = (int) (Math.random() * (max - min));
b[i] = (int) (Math.random() * (max - min));
for (int j = 0; j < i; j++) {
if (a[i] == a[j]) {
i--;
}
if (b[i] == b[j]) {
i--;
}
}
}
System.out.println("a - > " + Arrays.toString(a));
System.out.println("b - > " + Arrays.toString(b));
for (int k = 0; k < a.length; k++) {
for (int l = 0; l < b.length; l++) {
if (a[k] == b[l]) {
s[l] = b[l];
}else {
}
}
}
System.out.println("(a ∪ (b/(a ∩ b)) - > " + Arrays.toString(s));
return null;
}
public static boolean hasValue(int[] array, int value) {
for (int i = 0; i < array.length; i++) {
if (array[i] == value) {
return true;
}
}
return false;
}
}
Is there any way to create the array without the incorrect 0s? (I say incorrect because it is possible to have 0 in both a and b).
Any help/clarification is appreciated.
First, allocate an array large enough to hold the intersection. It needs to be no bigger that the smaller of the source arrays.
When you add a value to the intersection array, always add it starting at the beginning of the array. Use a counter to update the next position. This also allows the value 0 to be a valid value.
Then when finished. use Array.copyOf() to copy only the first part of the array to itself, thus removing the empty (unfilled 0 value) spaces. This works as follow assuming count is the index you have been using to add to the array: Assume count = 3
int[] inter = {1,2,3,0,0,0,0};
inter = Arrays.copyOf(inter, count);
System.out.println(Arrays.toString(inter);
prints
[1,2,3]
Here is an approach using a List
int[] b = {4,3,1,2,5,0,2};
int [] a = {3,5,2,3,7,8,2,0,9,10};
Add one of the arrays to the list.
List<Integer> list = new ArrayList<>();
for(int i : a) {
list.add(i);
}
Allocate the intersection array with count used as the next location. It doesn't matter which array's length you use.
int count = 0;
int [] intersection = new int[a.length];
Now simply iterate thru the other array.
if the list contains the value, add it to the intersection array.
then remove it from the list and increment count. NOTE - The removed value must be converted to an Integer object, otherwise, if a simple int value, it would be interpreted as an index and the value at that index would be removed and not the actual value itself (or an Exception might be thrown).
once finished the intersection array will have the values and probably unseen zeroes at the end.
for(int i = 0; i < b.length; i++) {
int val = b[i];
if (list.contains(val)) {
intersection[count++] = val;
list.remove(Integer.valueOf(val));
}
}
To shorten the array, use the copy method mentioned above.
intersection = Arrays.copyOf(intersection, count);
System.out.println(Arrays.toString(intersection));
prints
[3, 2, 5, 0, 2]
Note that it does not matter which array is which. If you reverse the arrays for a and b above, the same intersection will result, albeit in a different order.
The first thing I notice is that you are declaring your intersection array at the top of the method.
int[] s = new int[nbr];
You are declaring the same amount of space for the array regardless of the amount you actually use.
Method Arrays.toString(int []) will print any uninitialized slots in the array as "0"
There are several different approaches you can take here:
You can delay initializing the array until you have determined the size of the set you are dealing with.
You can transfer your content into another well sized array after figuring out your result set.
You could forego using Array.toString, and build the string up yourself.
I need to sort an array. I write code, i use insertion sort, but for big n this code work so slow. How optimize my code. May be there is another algorithm.
public void insertionSort(ArrayList<Integer> arrayList) {
int n = arrayList.size();
int in, out;
for(out = 1; out < n; out++)
{
int temp = arrayList.get(out);
in = out;
while (in > 0 && arrayList.get(in-1) > temp)
{
arrayList.set(in, arrayList.get(in-1));
in--;
}
arrayList.set(in,temp);
}
print(arrayList);
}
You can use counting sort instead of insertion sort. Because counting sort takes a linear time, but insertion sort at worst takes О(n^2)
Here is example of using counting sort:
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void print(int []a){
System.out.println(Arrays.toString(a));
}
public static void countingSort(int []a, int []b, int n, int k){
int []c = new int [k];
for(int i=0; i<k; i++)
c[i] = 0;
for(int j=0; j<n; j++){
c[a[j]] = c[a[j]]+1;
}
for(int i=1; i<k; i++){
c[i] = c[i]+c[i-1];
}
for(int j=n-1; j>=0; j--){
c[a[j]] = c[a[j]]-1;
b[c[a[j]]] = a[j];
}
for(int i=0; i<n; i++)
a[i] = b[i];
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Random ran = new Random();
int n = Integer.parseInt(in.nextLine());
int []a = new int[n];
int []b = new int[n];
int k = 5; // max value on the array
for(int i=0; i<n; i++)
a[i] = ran.nextInt(k);
print(a);
countingSort(a,b,n,k);
print(a);
}
}
You should look into QuickSort or MergeSort if you want faster sorting algorithms. Unlike InsertionSort (and SelectionSort), they are recursive, but still fairly easy to implement. You can find many examples if you look around on the internet.
As Anna stated above, counting sort can be a really good algorithm, considering you don't have a really large data set and the data is not sparse.
For example, an array of size 10k with 100 elements duplicated will have much better space efficiency than an array of size 10k with all unique elements and spread in a sparse fashion.
For example, the following array -> [5,5,4,...,2,2,1,1,5,6,7,8] will need a space of an array of size 8 (1 being the minimum and 8 being the maximum) while,
This array -> [5,100,6004,3248,45890,2384,128,8659,...,3892,128] will need a space of an array at least of size 45886 (5 being the minimum and 45890 being the maximum).
So, I'll suggest you use this algorithm when you know that the data set you have is evenly distributed within an acceptable range which won't make your program run out of memory. Otherwise you can go with something like quicksort or mergesort. That gets the work done just fine.
That being said, Anna's implementation of counting sort seemed a little over coded to me personally, so here's me sharing my implementation.
public int[] countSort(int[] nums) {
int min = nums[0], max = nums[0], counterLength, start = 0;
int[] counter;
// To dynamically allocate size to the counter.
// Also an essential step if there are negative elements in the input array.
// You can actively avoid this step if you know:
// 1. That the elements are not going to be negative.
// 2. The upper bound of the elements in the array.
for (int i : nums) {
if (i > max)
max = i;
else if (i < min)
min = i;
}
counterLength = max - min + 1;
counter = new int[counterLength];
for (int i : nums)
counter[i - min]++;
for (int i = 0; i < counterLength; i++) {
if (counter[i] > 0) {
int end = start + counter[i];
Arrays.fill(nums, start, end, i + min);
start = end;
}
}
return nums;
}
Yes, this is homework, but I need some help with it. I have been able to make it sort through the highest number, but none of the numbers are correct after that. List of numbers: http://pastebin.com/Ss1WFGv1
Right now, we are learning arrays, so is this simply trying to shoot a fly with a cannonball?
package hw2;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
public class HW2 {
public static ArrayList<Integer> nums1 = new ArrayList<Integer>();
public static int size = 0;
public static void main(String[] args) throws Exception {
ArrayList<Integer> sortedNums = new ArrayList<Integer>();
readFile();
System.out.println("Name: Jay Bhagat" + "\n" + "Email: xxxxxx");
size = nums1.size();
for(int l = 0; l<=10;l++){
nums1.set(sortThis(nums1, l), 90009);
System.out.println("\n\n");
}
// for (int k = 0; k <= size - 1; k++) {
// System.out.println("Number " + (k + 1) + sortedNums.get(k));
//
// }
}
public static void readFile() throws Exception {
BufferedReader reader = new BufferedReader(new FileReader("L:\\numbers.txt"));
while (reader.readLine() != null) {
nums1.add(Integer.parseInt((reader.readLine())));
}
reader.close();
}
public static int sortThis(ArrayList<Integer> current, int offset) {
int j = 0;
int tempNum = 0;
int curNum = 0;
int finalIndex = 0;
int prevIndex = 0;
int curIndex = 0;
for (j = 0; j < size-offset; j++) {
curIndex = j;
nums1.trimToSize();
curNum = current.get(j);
//Thread.sleep(1000);
if(curNum!=90009){
if (curNum > tempNum) {
tempNum = curNum;
System.out.println(tempNum);
prevIndex = j;
finalIndex = prevIndex;
}
if (curNum < tempNum) {
finalIndex = prevIndex;
}
}
}
return finalIndex;
}
}
An approach that lets you make just one pass through the list and doesn't require sorting:
Declare an array of 5 integers: int[] largest = new int[5];
Put the first 5 elements in the ArrayList into largest.
Starting with the 6th element, look at each element N in the ArrayList, and if N is larger than any element in largest, throw out the smallest number currently in largest and replace it with N.
If you need to exclude duplicates, the algorithm can be modified easily (just skip over any ArrayList element that's already in largest).
Why not use Collections.sort(List list) or Arrays.Sort(arr). This will save much of effort. Or is it part of your task?
Assuming your collection is sorted, and you want the last 5 elements, try this out:
for (int i = sortedNums.size() - 5; i < sortedNums.size(); ++i) {
System.err.println(sortedNums.get(i));
}
How I would go about doing this:
Create a temporary ArrayList, as a copy of the initial one.
After each largest element is found, remove it from the temporary ArrayList and add it to your 5 largest numbers
Repeat until complete
edit* This does not require your elements to be sorted, and has a fairly poor efficiency as a result
I assume you do not have the liberty to use sort and suchlike, considering this is a homework. So here is outline of an algorithm that you can try to implement
create an array of five integers (we will keep this sorted)
for each element in the list
find the index of the element in the array that it is greater than
if no such element exists in the array (i.e. it is smaller than all elements in the array)
continue on to the next element in the list
else
push all elements in the array to one index below, letting them fall off the
edge if need be (e.g. if the number in list is 42 and the array has
45 and 40 at index 3 and 2 respectively then
move arr[1] to arr[0], and arr[2] (40) to arr[1] and set arr[2] = 42)
end if
end for
At the end the array will have the five elements
I will leave one question for you to answer (it is important): what should you set the array to initially?
You only need two lines of code:
Collections.sort(nums1);
List<Integer> high5 = nums1.subList(nums1.size() - 5, nums1.size());
If you must "do it yourself", the simplest way to sort is a bubble sort:
iterate over the list
swap adjacent numbers if they are in the wrong order
repeat n times
Not efficient but very easy to code.
I have managed to convert it to output the values from the 2D array, but have no idea how to get the position.
Here is my code:
public static int[] convert(int [][]twodarray)
{
int[] onedarray = new int[twodarray.length * twodarray.length];
for(int i = 0; i < twodarray.length; i ++)
{
for(int s = 0; s < twodarray.length; s ++)
{
onedarray[(i * twodarray.length) + s] = twodarray[i][s];
}
}
return onedarray;
}
public static int [] printonedarray(int [] onedarray)
{
System.out.print("onedarray: ");
for(int i = 0; i < onedarray.length; i++)
{
System.out.print(onedarray[i] + "\t");
}
System.out.println();
return onedarray;
}
assuming that your 2-d array is not a jagged array, than the original cordinates for A[i] should be A[i/x][i%x] where x is the original length of the least significant column your 2/d array
Okay, I am not really sure if I get you correclty. But I understand it this way:
You have a 2 dim. array and want to convert it to a 1 dim. array.
Therefore you want to ready the first coloumn and the first line.
Then you want to add this value at the forst position of the 1 dim. array.
Then you read the next row and want to add this value and so on.
If I am right I suggest an arrayList for your 1 dim array. Because you don't know how deep the coloumns are. And ArrayLists are dynamic. You can simply add an element and don't need to give a position.
Your code suggestion was pretty good and I just converted it to an ArrayList.
import java.util.ArrayList;
public class test
{
public static ArrayList<Integer> convert(int [][]twodarray)
{
ArrayList<Integer> onedarray = new ArrayList<Integer> ();
for(int i = 0; i < twodarray.length; i ++)
{
for(int s = 0; s < twodarray[i].length; s ++)
{
onedarray.add(twodarray[i][s]);
}
}
return onedarray;
}
public static ArrayList<Integer> printonedarray(ArrayList<Integer> onedarray)
{
System.out.print("onedarray: ");
for(int i = 0; i < onedarray.size(); i++)
{
System.out.print(onedarray.get(i) + "\t");
}
System.out.println();
return onedarray;
}
}
If I missed your question I am sorry for a "wrong" answer.
I hope it will help you!