find all possible combinations of a set in java - java

okay so we basically have this question to answer, but I am very confused and don't know how to use recursion to get all possible combinations.. Please someone save me!
Write a public static method threadings, which takes an int n (representing the number of beads on each necklace) and a Set of Strings (representing the available bead colours; your code must not alter this Set),and returns a Set of ArrayLists of Strings, representing all the orders in which n beads of the given colours can be threaded. If n < 1, return a Set containing just one, empty, ArrayList.
Examples of correct behaviour:
• threadings(0, {red,green}) = {[]}
• threadings(1, {red,green}) = {[red],[green]}
• threadings(2, {red,green})
= {[red,red],[red,green],[green,red],[green,green]}
• threadings(3, {red}) = {[red,red,red]}
Hint: you will probably want threadings to call itself recursively, although
full marks are available for any correct method.
This is what I have written until now:
public static HashSet<ArrayList<String>> threadings (int n, Set<String> colours){
HashSet<ArrayList<String>> result= new HashSet<ArrayList<String>>();
ArrayList<String> inresult= new ArrayList<String>();
String[] col= new String[colours.size()];
if (n==0){
result.add(inresult);
return result;
}else{
}
}

Try this:
public static HashSet<ArrayList<String>> threadings (int n, Set<String> colours) {
List<String> colorsList = new ArrayList<>(colours);
ArrayList<String> resultList = new ArrayList<>();
HashSet<ArrayList<String>> result = new HashSet<ArrayList<String>>();
int carry;
int[] indices = new int[n];
do
{
for(int index : indices) {
resultList.add(colorsList.get(index));
}
result.add(resultList);
resultList = new ArrayList<>();
carry = 1;
for(int i = indices.length - 1; i >= 0; i--)
{
if(carry == 0)
break;
indices[i] += carry;
carry = 0;
if(indices[i] == colorsList.size())
{
carry = 1;
indices[i] = 0;
}
}
}
while(carry != 1);
return result;
}

Related

Print variables, excluding ones that are zero

Let's say I have five int variables that are prompted for user input. User keys in the five value and two of those values are 0. I would like to ONLY print out values that are greater than zero.
int v1 = 1;
int v2 = 30;
int v3 = 0;
int v4 = 37;
int v5 = 0;
I would like to write a dynamic print statement that would exclude the int variables with Zero value.
Currently, my print statement displays all values:
System.out.printf("%s %d%n%s %d%n%s %d%n%s %d%n%s %d%n","V1;","v1","V2:","v2","V3:","v3","V4:","v4","V5:","v5");
I tried writing if-else statements but that became very cumbersome.
Create a new method printNonZeroVars(Integer... ints).
public static void main(String[] args) {
int v1 = 1;
int v2 = 30;
int v3 = 0;
int v4 = 37;
int v5 = 0;
printNonZeroVars(v1, v2, v3, v4, v5)
}
public void printNonZeroVars(int... ints) {
for (int i = 0; i < ints.length; i++) {
if (ints[i] > 0) {
System.out.printf("V%d%d%n", i, ints[i]);
}
}
}
I would use an array.
Iterate over the array and with an if you can check whether your current value is 0.
So a simple way of achieving this would be to use some sort of Array/List.
ArrayList<Integer> list = new ArrayList<Integer>()
// Or as pointed out by David a better way would be to declare the list as
List<Integer> list = new ArrayList<>();
list.add(5);
list.add(1);
list.add(0);
....
Once you have the list you can use a loop to loop through the list and do relevant checks - something like this
String str = "";
for(int i=0; i<list.size(); i++) {
if(list.get(i) == 0) {
continue;
}
str += "v"+i + ":" + Integer.toString(list.get(i));
}
System.out.println(str);
Its pseudo but should give you a good head start :)

Calculation of average required series of integers, equal to a defined double

Hello!
I am trying to make a Java program to generate a series of Integers from a given array, such that the average of the selected integers is equal to a user-defined double.
Now, let's say the User defines the target as 46.00.
ArrayList<Integer> usableItems = new ArrayList<>();
Here, the user specifies the size and each integer into the array. Like this.
System.out.println("Enter number of elements of usable integers: ");
int siz=0;
siz = Integer.parseInt(in.nextLine());
ArrayList<Integer> usableItems = new ArrayList<>();
for (int i=0 ; i<siz ; i++)
{
try {
int j = i+1;
System.out.println("Enter element "+j+": ");
usableItems.add(Integer.parseInt(in.nextLine()));
} catch (Exception e)
{
System.out.println(e.getMessage());
break;
}
}
Let's say, this is the specified array:
[20,25,30,35,50]
So, it should process now, so that I get this output:
Specified target = 46.00
Series = 50,50,50,50,30
As the average of the above outputted series is equal to 46.
The number of integers in the Series (which is 5), need not be equal to the size of the usableItems.
I tried to find an accurate algorithm, but I don't get it how to.
Any helps/suggestions are surely appreciated!
Brute-force recursive implementation returning the shortest possible series:
public List<Integer> matchAverage(double target, List<Integer> items) {
for (int i = 1; i <= 50; i++) { // arbitrary limit of 50
List<Integer> match = matchAverage(target, items, new ArrayList<>(), 0, i);
if (match != null) return match;
}
throw new RuntimeException("Average not found.");
}
private List<Integer> matchAverage(double target, List<Integer> items, List<Integer> selected, int sum, int left) {
for (int i = 0; i < items.size(); i++) {
Integer item = items.get(i);
selected.add(item);
sum += item;
if (left == 1) {
if (sum / (double) selected.size() == target) {
return selected;
}
} else {
List<Integer> match = matchAverage(target, items.subList(i, items.size()), selected, sum, left - 1);
if (match != null) return match;
}
sum -= item;
selected.remove(selected.size() - 1);
}
return null;
}
You can probably do this a lot faster by only checking items that get you closer to the target.

How to store all entered array elements

I'm new at programming. I have to write a code, main requirements - user chooses the sorting method (one is already added, the second one I will add later), enters the amount of elements in the array, enters the elements and then the code sorts them. But it looks like the code only takes the last entered element and tries to sort it. What do I have to do to make it sort all entered elements?
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("181RDB094 Līva Gundega Ermansone 1");
System.out.print("method:");
int M;
if (sc.hasNextInt())
M = sc.nextInt();
else {
System.out.println("input-output error");
sc.close();
return;
}
System.out.print("count:");
int count = sc.nextInt();
int[] masīvs = new int[count];
System.out.println("items:");
masīvs = new int[count];
for (int i = 0; i < count; i++) {
masīvs[i] = sc.nextInt();
}
System.out.println("result:");
if (M == 1) {
int[] b = new int[count];
int[] less = new int[count];
int[] equal = new int[count];
int k;
for (int i = 0; i < count; i++)
for (int j = 0; j < count; j++) {
if (masīvs[i] == masīvs[j]) {
equal[i] = i++;
} else if (masīvs[i] > masīvs[j]) {
less[i] = i++;
}
}
for (int i = 0; i < count; i++) {
k = less[i];
for (int j = 0; j < equal[i]; j++) {
b[k + j] = masīvs[i];
}
}
for (int i = 0; i < count; i++) {
masīvs[i] = b[i];
System.out.print(masīvs[i] + " ");
}
} else if (M == 2) {
} else {
System.out.println("input-output error");
return;
}
}
Sorry for the ugly code, it's just a draft.
Expected:
181RDB094 Līva Gundega Ermansone 1
method:1
count:4
items:
13
31
55
2
result:
55 31 13 2
Actual results:
181RDB094 Līva Gundega Ermansone 1
method:1
count:4
items:
13
31
55
2
result:
2 2 2 0
You can add a simple for loop after filling your array to check the contents. There, you can see that all entries are written into the array correctly.
This will output:
Array:13
Array:31
Array:55
Array:2
for (int i = 0; i < masīvs.length; i++) {
System.out.println("Array:" + masīvs[i]);
}
The sorting method you are following fixes a set of equal elements at their proper position by finding the no of elements less than those elements.
The problem in sorting lies in finding the no of elements less and equal to.
equal[i]++; instead of equal[i]=i++;
Similarly,
less[i]++; instead of less[i]=i++;
If you're using Java 8 or more recent, you may be able to use the ArrayList class (with the Integer class) instead of an 1D array (i.e. int[] var = new int[x]); it would allow you to use its sort(Comparator) method instead.
You would have to create a Comparator instance (lambda function, or anonymous) or an implementing class, unless you want to use the natural ordering of those.
It would give you something around those two lines:
ArrayList<Integer> var = new ArrayList<>();
and var.sort(); (assuming you use the natural ordering)
It might however be harder to manipulate at first, if you're new to the Java Collection Framework, so don't hesitate to ask questions.
P.S.: I might have misunderstood the code, so just tell me so I can fix my answer.
P.S.S.: Somewhat unrelated, and it's probably in your mind (ignore that part then), but I would recommend you to refactor that into much more smaller methods/functions.
I think that your code organization is very bad. It's easier to give you more correct solution, than count and fix your problem:
public class Foo {
public static void main(String... args) {
final BiFunction<int[], Comparator<Integer>, int[]> sort =
(items, comparator) -> Arrays.stream(items)
.boxed()
.sorted(comparator)
.mapToInt(i -> i)
.toArray();
try (Scanner scan = new Scanner(System.in)) {
Comparator<Integer> comparator = getSortingMethod(scan);
int[] items = getItems(scan);
int[] sorted = sort.apply(items, comparator);
System.out.println(Arrays.toString(sorted));
}
}
private static final Comparator<Integer> SORT_ASC = Comparator.naturalOrder();
private static final Comparator<Integer> SORT_DESC = Comparator.reverseOrder();
private static final Comparator<Integer> SORT_NULL = (one, two) -> {
throw new IllegalArgumentException("input-output error");
};
private static Comparator<Integer> getSortingMethod(Scanner scan) {
System.out.println("181RDB094 Līva Gundega Ermansone 1");
System.out.print("method:");
try {
int M = scan.nextInt();
if (M == 1)
return SORT_DESC;
if (M == 2)
return SORT_ASC;
return SORT_NULL;
} catch(RuntimeException e) {
return SORT_NULL;
}
}
private static int[] getItems(Scanner scan) {
System.out.print("count:");
int[] items = new int[scan.nextInt()];
System.out.println("items:");
for (int i = 0; i < items.length; i++)
items[i] = scan.nextInt();
return items;
}
}

How to Find Union of Two String Arrays

I am trying to find the union of two string arrays. I have created a new array and have copied all the data from the first set into the new array. I am having trouble adding the information from the second set into the new array.
I need to use loops to search the second array and find the duplicates. I keep getting an ArrayIndexOutOfBoundsException.
Here is my current code:
static String[] union(String[] set1, String[] set2) {
String union[] = new String[set1.length + set2.length];
int i = 0;
int cnt = 0;
for (int n = 0; n < set1.length; n++) {
union[i] = set1[i];
i++;
cnt++;
}
for (int m = 0; m < set2.length; m++) {
for (int p = 0; p < union.length; p++) {
if (set2[m] != union[p]) {
union[i] = set2[m];
i++;
}
}
}
cnt++;
union = downSize(union, cnt);
return union;
}
The standard way of doing intersections or unions is using a set. You should use the Set class from collections framework.
Create two arraylist objects for your two arrays.
Define a Set object.
Add both the arraylist objects into the Set using addAll method.
As set holds unique elements, the set forms the union of
both arrays.
//push the arrays in the list.
List<String> list1 = new ArrayList<String>(Arrays.asList(stringArray1));
List<String> list2 = new ArrayList<String>(Arrays.asList(stringArray2));
HashSet <String> set = new HashSet <String>();
//add the lists in the set.
set.addAll(list1);
set.addAll(list2);
//convert it back to array.
String[] unionArray = set.toArray(new String[0]);
Using Set is going to be one of the easiest way:
public static String[] unionOf(String[] strArr1, String[] strArr2) {
Set<String> result = new HashSet<String>();
result.addAll(Arrays.asList(strArr1));
result.addAll(Arrays.asList(strArr2));
return result.toArray(new String[result.size()]);
}
There are also other utilities that can help in similar work, e.g. Guava:
public static String[] unionOf(String[] strArr1, String[] strArr2) {
return Sets.union(Sets.newHashSet(strArr1),
Sets.newHashSet(strArr2))
.toArray(new String[0]);
}
You have several problems with this part of your code:
for(int m = 0; m < set2.length; m++)
for(int p = 0; p < union.length; p++)
if(set2[m] != union[p])
{
union[i] = set2[m];
i++;
}
cnt++;
First, you should be using !equals() instead of != to compare strings. Second, despite the indenting, the statement cnt++ is not part of the outer loop. You don't need both i and cnt; their values should always match. Finally, you are adding set2[m] once for each element of union that is different from it. You only want to add it once. Here's a version that should work:
static String[] union( String[] set1, String[] set2 )
{
String union[] = new String[set1.length + set2.length];
System.arraycopy(set1, 0, union, 0, set1.length); // faster than a loop
int cnt = set1.length;
for(int m = 0; m < set2.length; m++) {
boolean found = false;
for(int p = 0; p < union.length && !found; p++) {
found = set2[m].equals(union[p]);
}
if(!found)
{
union[cnt] = set2[m];
cnt++;
}
}
union = downSize( union, cnt );
return union;
}
As other posters have noted, an alternative approach is to use a HashSet<String>, add the elements found in the two arrays, and turn the result back into an array.
You get ArrayIndexOutOfBoundsException on this line:
union[i] = set2[m];
because you keep increasing i somewhere around: set2.length * union.length times (nested loops).
Doing what R.J wrote will not give you the union - you'll have many duplicate items since by doing: set2[m].equals(union[p]) you compare every member of set2 to all the members of union and for each member that it's not equal to - you add it. so you end up adding the same items multiple times!
The right way to do it is like Deepak Mishra suggested by using Set which will "take care" of the duplicates.
Example:
int[] a = {1,2,3,4,5};
int[] b = {4,5,6,7};
Set union = new HashSet<Integer>();
for(int i=0; i<a.length; i++) union.add(a[i]);
for(int i=0; i<b.length; i++) union.add(b[i]);
Object[] ans = union.toArray();
for(int i=0; i<ans.length; i++)
System.out.print(ans[i]+" ");
will output:
1 2 3 4 5 6 7
Since it's HW I won't write the code for the answer, but I'll give you a tip: doing it your way requires O(n^2) - if you'll think a bit I'm sure that you can find a way to do it in a better time, say, O(n log n)...
Though using the SETS is the best solution, here is a simple solution.
private static String getUnion(String a, String b, boolean ignoreCase) {
String union = "";
if (a == null || b == null || a.length() < 1 || b.length() < 1) {
return union;
}
char[] shortest;
char[] longest;
if (ignoreCase) {
shortest = (a.length() <= b.length() ? a : b).toLowerCase().toCharArray();
longest = (a.length() <= b.length() ? b : a).toLowerCase().toCharArray();
} else {
shortest = (a.length() <= b.length() ? a : b).toLowerCase().toCharArray();
longest = (a.length() <= b.length() ? b : a).toLowerCase().toCharArray();
}
StringBuilder sb = new StringBuilder();
for (char c : shortest) {
for (int i = 0; i < longest.length; i++) {
if (longest[i] == c) {
sb.append(c);
}
}
}
union = sb.toString();
return union;
}
and following are few tests.
public static void main(String[] args) {
System.out.println("Union of '' and BXYZA is " + getUnion("", "BXYZA", true));
System.out.println("Union of null and BXYZA is " + getUnion(null, "BXYZA", true));
System.out.println("Union of ABC and BXYZA is " + getUnion("ABC", "BXYZA", true));
System.out.println("Union of ABC and BXYZA is " + getUnion("ABC", "bXYZA", false));
}

Eliminating Recursion

I've just been looking at the following piece of code
package test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(final String[] args) {
final int sizeA = 3;
final int sizeB = 5;
final List<int[]> combos = getAllCombinations(sizeA-1, sizeB);
int counter = 1;
for(final int[] combo : combos) {
System.out.println("Combination " + counter);
System.out.println("--------------");
for(final int value : combo) {
System.out.print(value + " ");
}
System.out.println();
System.out.println();
++counter;
}
}
private static List<int[]> getAllCombinations(final int maxIndex, final int size) {
if(maxIndex >= size)
throw new IllegalArgumentException("The maximum index must be smaller than the array size.");
final List<int[]> result = new ArrayList<int[]>();
if(maxIndex == 0) {
final int[] array = new int[size];
Arrays.fill(array, maxIndex);
result.add(array);
return result;
}
//We'll create one array for every time the maxIndex can occur while allowing
//every other index to appear, then create every variation on that array
//by having every possible head generated recursively
for(int i = 1; i < size - maxIndex + 1; ++i) {
//Generating every possible head for the array
final List<int[]> heads = getAllCombinations(maxIndex - 1, size - i);
//Combining every head with the tail
for(final int[] head : heads) {
final int[] array = new int[size];
System.arraycopy(head, 0, array, 0, head.length);
//Filling the tail of the array with i maxIndex values
for(int j = 1; j <= i; ++j)
array[size - j] = maxIndex;
result.add(array);
}
}
return result;
}
}
I'm wondering, how do I eliminate recursion from this, so that it returns a single random combination, rather than a list of all possible combinations?
Thanks
If I understand your code correctly your task is as follows: give a random combination of numbers '0' .. 'sizeA-1' of length sizeB where
the combination is sorted
each number occurs at least once
i.e. in your example e.g. [0,0,1,2,2].
If you want to have a single combination only I'd suggest another algorithm (pseudo-code):
Randomly choose the step-up positions (e.g. for sequence [0,0,1,1,2] it would be steps (1->2) & (3->4)) - we need sizeA-1 steps randomly chosen at sizeB-1 positions.
Calculate your target combination out of this vector
A quick-and-dirty implementation in java looks like follows
// Generate list 0,1,2,...,sizeB-2 of possible step-positions
List<Integer> steps = new ArrayList<Integer>();
for (int h = 0; h < sizeB-1; h++) {
steps.add(h);
}
// Randomly choose sizeA-1 elements
Collections.shuffle(steps);
steps = steps.subList(0, sizeA - 1);
Collections.sort(steps);
// Build result array
int[] result = new int[sizeB];
for (int h = 0, o = 0; h < sizeB; h++) {
result[h] = o;
if (o < steps.size() && steps.get(o) == h) {
o++;
}
}
Note: this can be optimized further - the first step generates a random permutation and later strips this down to desired size. Therefore it is just for demonstration purpose that the algorithm itself works as desired.
This appears to be homework. Without giving you code, here's an idea. Call getAllCombinations, store the result in a List, and return a value from a random index in that list. As Howard pointed out in his comment to your question, eliminating recursion, and returning a random combination are separate tasks.

Categories