How to generate arrays with some very specific constraints - java

I want to print 100 int arrays according to some specific constraints.
each array can have a variable length from 2 to 10.
every item in each array must be unique
items in each array are sorted from the lowest to the highest
there are no identical arrays, meaning two arrays having same lenght and same items
At the moment I have this code
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
public class prova {
public static void main(String[] args) {
Integer[] elements = new Integer[]{1,2,3,4,5,6,7,8,9,10};
Set<List<Integer>> seenAlready = new HashSet<>();
for (int i = 0; i < 100; i++) {
final Integer[] array = generateRandomArrayFromElements(elements);
Arrays.sort(array);
if (seenAlready.add(Arrays.asList(array)))
System.out.println(Arrays.toString(array));
}
}
private static Integer[] generateRandomArrayFromElements(Integer[] elements) {
int size = ThreadLocalRandom.current().nextInt(1, elements.length) + 1;
Integer[] array = new Integer[size];
ArrayList<Integer> usedIndices = new ArrayList<>(size);
for (int i = 0; i < array.length; i++) {
int randomIndex = getUniqueRandomIndex(usedIndices, size);
usedIndices.add(randomIndex);
array[i] = elements[randomIndex];
}
return array;
}
private static int getUniqueRandomIndex(ArrayList<Integer> usedIndices, int max) {
int randomIndex = ThreadLocalRandom.current().nextInt(0, max);
final boolean contains = usedIndices.contains(randomIndex);
if (contains)
randomIndex = getUniqueRandomIndex(usedIndices, max);
return randomIndex;
}
}
The problem is that it just generates arrays too similar too each other.
They all look the same!
Have a look at one of its possible outputs:
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5, 6, 7]
[1, 2]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I'm never getting arrays like:
[3,4,8,9]
[2,3,6,7,8]
Everytime they start with [1,2,3,4] and so on!
I don't get it!

The problem is that You are generating index in range from 0 to array.length.
So if the array size is 2, then Your range is <0,2)
If the array size is 3, then Your range is <0,3)
...
If the array size is 10, then Your range is <0,10)
And in that situation there is no way to generate different results than You showed us.
Spots to fill |Elements to choose from based on range
=======================================
[_,_] |[1,2,................] range <0,2)
[_,_,_] |[1,2,3,..............] range <0,3)
[_,_,_,_] |[1,2,3,4,............] range <0,4)
...
You should invoke it like this int randomIndex = getUniqueRandomIndex(usedIndices, elements.length);
Notice that max changed to elements.length.

1 - Start to generate 100 empty arrays with a variable length from 2 to 10.
2 - Count the total size.
3 - Generate x uniques integers and add them to a Set.
Set<Integer> set = new HashSet<Integer>();
while(set.size()< xxx) {
set.add(generateRandomInteger());
}
Collections.sort(set);
(where xxx is the total array size
4 - add the integers into your arrays.

Related

How to populate a 2d array with values from a 1d array?

I have a single array populated with some values that I receive from another method, and I want to populate a bidimensional array with values from the first, example:
int[] singleArray; // there's no values here to demonstrate,
// let's think that's populated
int[][] bidimArray = new int[80][80];
for (int i = 0; i < 80; i++) {
for (int j = 0; j < 80; j++) {
for (int x = 0; x < singleArray.length; x++) {
bidimArray[i][j] = singleArray[x];
}
}
}
I thought in the solution above, besides it seems very ugly solution, it only saves the last position of singleArray in bidimArray[][]. May anyone help me, please?
There is no need for the third for loop here. This is where you went wrong. The change to your code is to simply increment x for every value entered into the new 2D array and omitting the third for loop.
int[] singleArray;
int[][] bidimArray = new int[80][80];
int x = 0;
for (int i = 0; i < 80; i++) {
for (int j = 0; j < 80; j++) {
bidimArray[i][j] = singleArray[x];
x++;
}
}
You can also combine the two inner lines in the loop like this:
bidimArray[i][j] = singleArray[x++];
As pointed out in the comments, you should not hard code array sizes. For your approach, you will have to make sure that the singleArray contains at least 80*80 elements. If this is not given, you should make sure to check that constraint beforehand.
Circular populating of a 2d array 8x7 with values from a 1d array 6. It works the same with larger and smaller arrays regardless of size:
int[] arr1 = {1, 2, 3, 4, 5, 6};
int m = 8;
int n = 7;
int[][] arr2 = IntStream.range(0, m)
.mapToObj(i -> IntStream.range(0, n)
.map(j -> arr1[(j + i * n) % arr1.length])
.toArray())
.toArray(int[][]::new);
// output
Arrays.stream(arr2).map(Arrays::toString).forEach(System.out::println);
[1, 2, 3, 4, 5, 6, 1]
[2, 3, 4, 5, 6, 1, 2]
[3, 4, 5, 6, 1, 2, 3]
[4, 5, 6, 1, 2, 3, 4]
[5, 6, 1, 2, 3, 4, 5]
[6, 1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 1]
[2, 3, 4, 5, 6, 1, 2]
See also: Copying a 1d array to a 2d array

Insert column in desired location of 2D array

I'm looking to choose a column of my array, lets say column 2. I want this column to be inserted at a specific location in the 2D array, lets say column 4.
For example:
1 3 5 5 2
2 4 6 2 1
3 6 9 1 1
The desired output would be:
1 5 5 3 2
2 6 2 4 1
3 9 1 6 1
I know I could loop the following code until I 1 by 1 swap every column until the column is in the desired location.
for (int[] array1 : array) {
int temp = array1[col1];
array1[col1] = array1[col1];
array1[col2] = temp;
}
However, if I'm using large matrices such as 30 columns wide, this would be incredibly inefficient. Is there a way to insert the column anywhere in the 2D array without iterating through each swap until it is in the right spot?
Possibly, a performance may be improved by using parallel processing with streams.
IntStream of row indexes should be used to handle each row separately.
// basic shift method
// from, to - indexes starting from 1
public static void shiftArray(int[] arr, int from, int to) {
int tmp = arr[from - 1];
for (int i = from; i < to; i++) {
arr[i - 1] = arr[i];
}
arr[to - 1] = tmp;
}
public static void main(String[] args) {
int[][] arr2d = {
{1, 3, 5, 5, 2},
{2, 4, 6, 2, 1},
{3, 6, 9, 1, 1}
};
int fromColumn = 2;
int toColumn = 4;
IntStream.range(0, arr2d.length)
.parallel()
.forEach(i -> shiftArray(arr2d[i], fromColumn, toColumn)); // shift each row in parallel
// print the 2D array after shift
Arrays.stream(arr2d)
.map(Arrays::toString)
.forEach(System.out::println);
}
Output:
[1, 5, 5, 3, 2]
[2, 6, 2, 4, 1]
[3, 9, 1, 6, 1]
Try this.
public static void moveColumn(int[][] matrix, int from, int to) {
--from; --to; // If column number begins with zero, remove this line.
int srcPos = from < to ? from + 1 : to;
int destPos = from < to ? from : to + 1;
int length = Math.abs(from - to);
for (int[] array : matrix) {
int temp = array[from];
System.arraycopy(array, srcPos, array, destPos, length);
array[to] = temp;
}
}
and
int[][] matrix = {
{1, 3, 5, 5, 2},
{2, 4, 6, 2, 1},
{3, 6, 9, 1, 1}
};
moveColumn(matrix, 2, 4);
for (int[] row : matrix)
System.out.println(Arrays.toString(row));
output
[1, 5, 5, 3, 2]
[2, 6, 2, 4, 1]
[3, 9, 1, 6, 1]

Making a copy of the second half of an array

I want to make a function that takes as parameters an array and a boolean. The boolean tells the function if the rest of the division of the array is to be included. It then returns a new array which is the copy of the second half of the first:
secondHalf({1, 2, 3, 4, 5}, true) → {3, 4, 5}
secondHalf({1, 2, 3, 4, 5}, false) → {4, 5}
For this assignment, I'm not supposed to use any other classes.
Here's what I've attempted:
static int[] secondHalf(int[] vector, boolean include) {
int size = vector.length/2;
if(vector.length%2 == 0)
include = false;
if(include)
size ++;
int[] vector_2 = new int[size];
int i = 0;
while(i < size){
if(include)
vector_2[i] = vector[i+size-1];
vector_2[i] = vector[i+size+1];
i++;
}
return vector_2;
To find the size of vector_2, I've decided to use compound assignment operators. So the first part of this solution checks for the required condition and assigns a value to size in a single statement.
Since we know how many times to iterate over the loop, I think a for loop would be more appropriate than a while loop.
The loop retrieves all the values in vector from the middle of the array to the end of the array and places each value into vector_2.
static int[] secondHalf(int[] vector, boolean include) {
int size = vector.length/2 + (include && vector.length%2 != 0 ? 1 : 0);
int[] vector_2 = new int[size];
for(int i = 0; i < size; i++)
vector_2[i] = vector[vector.length - size + i];
return vector_2;
}
People have hinted at System#arraycopy, but with Arrays.copyOfRange there is an even simpler method, where you only have to define the proper start index and directly receive the copy.
The start index is array.length / 2 by default. Iff the include flag is true, then you have to add the remainder of dividing the array length by 2 to that.
An MCVE:
import java.util.Arrays;
public class ArrayPartCopy
{
public static void main(String[] args)
{
int array0[] = { 1, 2, 3, 4, 5 };
System.out.println("For " + Arrays.toString(array0));
System.out.println(Arrays.toString(secondHalf(array0, true)));
System.out.println(Arrays.toString(secondHalf(array0, false)));
int array1[] = { 1, 2, 3, 4 };
System.out.println("For " + Arrays.toString(array1));
System.out.println(Arrays.toString(secondHalf(array1, true)));
System.out.println(Arrays.toString(secondHalf(array1, false)));
}
static int[] secondHalf(int[] array, boolean include)
{
int start = array.length / 2;
if (include)
{
start += array.length % 2;
}
return Arrays.copyOfRange(array, start, array.length);
}
}
The output is
For [1, 2, 3, 4, 5]
[4, 5]
[3, 4, 5]
For [1, 2, 3, 4]
[3, 4]
[3, 4]

How can i print all possible order of an array with n integers using recursion?

For example, if I have an array a= {1, 2, 6, 10}, it should print all combinations of these 4 numbers, there should be 4! total combinations. An array of 5 integers will have a total of 5! combinations. (Different from previous versions because my number of parameters have to stay same. I am not allowed to put more than 3 paramrters in.
array a= {1, 2, 6, 10}
{1, 2, 10, 6}
{1, 6, 2, 10}
{1, 6, 10, 2}
.
.
.
{10, 6, 2, 1}
I am trying to solve this process using Recursion, any idea how? this is the code i have for now. Can anyone who has any idea whats going on please help me?
static void permutations (int a[], int n, int p){
if (p==n-1)
return ;
for (int i=p; i<n; i++){
int b[]=new int [n];
b[p]=a[i];
for (int j=0; j<i; j++)
b[j]=a[j];
for (int k =i+1; k<n; k++)
b[k]=a[k];
System.out.println(Arrays.toString(b));
return permutations(b, n, p+1);
}
}
best way to solve your problem to use Permutations concept in Algebra it's very useful way to get all possible combinations of a set.
you should also have knowledge in possibilities to solve this problem:
in this set {1, 2, 6, 10} element 1 has a k-Permutations which is 3
and this Permutations is : {2, 1, 6, 10},{6, 2, 1, 10},{10, 2, 6, 1}.
also element 2 has k-Permutations which is 2
2 Permutations is : {1, 6, 2, 10},{1, 10, 6, 2}.
element 6 has a k-Permutations which is 1
6 Permutations is : {1, 2, 10, 6}.
finally the total possible Permutations for all elements in set : 3 * 2 * 1 = 6.
simple algorithm to print all possible Permutations:
int[] num = {1,2,6,10};
int[] a = num.clone();
ArrayList<String> combs = new ArrayList<String>();
int temp;
for(int i=0; i < num.length-1; i++){
for(int j=i+1; j < num.length; j++){
temp = a[i];
a[i] = a[j];
a[j] = temp;
String obj = Arrays.toString(a);
if(!combs.contains(obj)){
combs.add(obj);
}
a = num.clone();
}
}
System.out.println("All possible order Combinations:");
for(String obj : combs){
System.out.println(obj);
}
output:
All possible order Combinations:
[2, 1, 6, 10]
[6, 2, 1, 10]
[10, 2, 6, 1]
[1, 6, 2, 10]
[1, 10, 6, 2]
[1, 2, 10, 6]
hope this would help.

How do you split an Array List into sublists everytime there is a duplicate value in the Array List

I have the following array list which contains the following
point ids (1,2,3,4,1,8,5,6,8,9,7,9). I am using Java 7
I was wondering how it could be split into sublists i.e the sublists below
(1,2,3,4,1)
(8,5,6,8)
(9,7,9)
I have had problems trying to use a loop within a loop (i.e check each point
from the outer loop with each of the other points in the inner loop) to get
index positions (starPosIndex and endPosIndex) where there are duplicate point ids and ArrayList.sublist(startPosIndex,endPosIndex) to get the correct sublist
int startPos = 0;
int endPos = 0;
for (int j = 0; j < polygonList3.size(); j++){
Point pointToCheck = polygonList3.get(j);
for (int k = 1; k < polygonList3.size(); k++){
Point pointToCheck2 = polygonList3.get(k);
if (pointToCheck.getID() == pointToCheck2.getID()){
startPos = startPos + endPos;
endPos = endPos + k;
//startPos = startPos + endPos;
//for (int startPos = j; startPos < polygonList3.size(); startPos = (startPos) + endPos) {
//endPos = Math.min(startPos + endPos, polygonList3.size());
finalPolygonLists.add(new ArrayList<Point>(polygonList3.subList(startPos, endPos)));//originalPtsSublist2);
//}
}
}
I would solve it in the following manner:
Allocate a HashSet to contain unique values encountered
Allocate a new list for the first sublist
Iterate over the whole list, adding each value to the set. When we encounter a value that is already in the set, we are done with the first sublist, so clear the set, and allocate a new sublist
After iteration, you will have your list of sublists, obtained in O(n) runtime
You can walk along the list, and create slices of the list (using List#subList) as you go. This can be done efficiently, by always checking whether the first element of the current segment of the list appears somewhere else in the list. If it does, you can store this "slice", and continue with the "tail" of the list. If it doesn't, you are finished (and the tail of the list may or may not be part of the result - that's up to you)
Implemented here as an example:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ListSlicing
{
public static void main(String[] args)
{
runTest(1,2,3,4,1,8,5,6,8,9,7,9);
runTest(1,2,3,4);
runTest(1,1,1,1);
runTest(1,2,1,2,1,2,1,2,1,2,1,2);
runTest();
}
private static void runTest(Integer ... numbers)
{
List<Integer> list = Arrays.asList(numbers);
System.out.println("Input: "+list);
System.out.println("Output: "+slices(list));
}
private static <T> List<List<T>> slices(List<T> input)
{
List<List<T>> slices = new ArrayList<List<T>>();
List<T> current = input;
while (current.size() > 0)
{
T first = current.get(0);
int appearance = current.subList(1, current.size()).indexOf(first);
if (appearance == -1)
{
slices.add(current);
return slices;
}
List<T> slice = current.subList(0, appearance+2);
slices.add(slice);
current = current.subList(appearance+2, current.size());
}
return slices;
}
}
The output is
Input: [1, 2, 3, 4, 1, 8, 5, 6, 8, 9, 7, 9]
Output: [[1, 2, 3, 4, 1], [8, 5, 6, 8], [9, 7, 9]]
Input: [1, 2, 3, 4]
Output: [[1, 2, 3, 4]]
Input: [1, 1, 1, 1]
Output: [[1, 1], [1, 1]]
Input: [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
Output: [[1, 2, 1], [2, 1, 2], [1, 2, 1], [2, 1, 2]]
Input: []
Output: []
The following code tracks the last position for each number and as soon as it founds a duplicate, it will create the sublist and clears all previously tracked entries.
List<Integer> list = Arrays.asList( 1,2,3,4,1,8,5,6,8,9,7,9);
List<List<Integer>> sublists = new ArrayList<>();
Map<Integer,Integer> lastPos = new HashMap<>();
for(int i = 0; i < list.size(); i++) {
Integer current = list.get(i);
if(lastPos.containsKey(current)){
sublists.add(list.subList(lastPos.get(current), i+1));
lastPos.clear();
} else {
lastPos.put(current, i);
}
}
System.out.println(sublists);

Categories