I have an arraylist of Strings that want to have all possible combinations stored into another collection.
For example:
[air,bus,car]
->
[air]
[bus]
[car]
[air,bus]
[air,car]
[bus,air]
[bus,car]
[car,air]
[car,bus]
[air,bus,car]
[air,car,bus]
...
[car,bus,air]
Repetitions are not important. The code right now I have is:
public ArrayList<String> comb(ArrayList<String> wrds, ArrayList<String> str, int size)
{
ArrayList<String> s = new ArrayList<String>();
s.addAll(str);
if(size != a1.size())
{
Iterator e = a1.iterator();
while(e.hasNext())
{
s.add((String)e.next());
}
size++;
}
}
I am trying to get it to recursively call itself so it can store the combinations. Can I get any help as to where or which part I am missing in my code?
Seeing as this is homework, I'll try to give you background to the answer.
The key to solving this is to use recursion.
First imagine you have two items in your array. You'd could remove the first item to give you your first combination. Adding the remaining item to the first item gives you the second combination. Removing the second item give you the third combination. Adding the remaining item gives you the forth combination. If you had ["air", "bus"] it'd be something like:
["air"]
["air", "bus"]
["bus"]
["bus", "air"]
A method that returns that might look like:
String[][] combinations(String[] strings)
The important things to note are the an array containing a single string can be passed to this method and it can return an array containing an array with a single string in it.
The problem is complicated a little because you have to keep a tally of the string combinations, so before we get to solving that, it's important that you understand recursion.
Imagine you wanted to write a multiplication method that takes two numbers and multiplies them but you only have addition and subtraction at your disposal. You could write a recursive function that adds one of the numbers to itself until the other number reaches an exit condition, something like:
public int multiply(int value1, int value2)
{
if (value1 > 1)
{
int remaining = value1 - 1;
return value2 + multiply(remaining, value2);
}
else
{
return value2;
}
}
You can do just the same thing with an array, only instead to exiting when the a value hit's 1 you exit when the array contains one item, something like:
public String[][] combinations(String[] strings)
{
if (strings.length > 1)
{
...
}
else
{
return new String[][]{strings};
}
}
For reasons with the Java API it's much easier to use java.util.List rather than arrays so you want something like:
public List<List<String>> combinations(List<String> strings)
{
if (strings.size()> 1)
{
...
}
else
{
List<List<String>> result = new ArrayList<List<String>>();
result.add(strings);
return result;
}
}
Now it's the ... that's the important bit. You need to keep an list-of-lists that will be the result and iterate over the strings. For each of the strings you can add that string to the results and then you need create a sub-list that is minus the current string, which you use to call the combinations method again iterating over the result adding the current string each list it contains. In code it looks something like:
public List<List<String>> combinations(List<String> strings)
{
if (strings.size() > 1)
{
List<List<String>> result = new ArrayList<List<String>>();
for (String str : strings)
{
List<String> subStrings = new ArrayList<String>(strings);
subStrings.remove(str);
result.add(new ArrayList<String>(Arrays.asList(str)));
for (List<String> combinations : combinations(subStrings))
{
combinations.add(str);
result.add(combinations);
}
}
return result;
}
else
{
List<List<String>> result = new ArrayList<List<String>>();
result.add(new ArrayList<String>(strings));
return result;
}
}
In summary, what you're doing is reducing the list of strings down to a single item, then combining it with the preceeding items to produce all the possible combinations as the thread returns up the call stack.
public static void combination(Object[] array){
for(int x = 0; x < (1 << array.length); x++){
System.out.print("[");
for(int y = 0; y < array.length; y++){
if(checkIsOn(x, y){
System.out.print(array[y]);
}
}
System.out.println("]");
}
}
public static boolean checkIsOn(int mast, int position){
return (mast & (1 << position) > 0);
}
Use the list as a parameter to the recursive function. You can call the function from within itself with a new list containing everything except the first item.
Related
I a having two string's
Here the + is missing after 5 characters so the answer is +5|. The logic I wrote has a problem when I use list1.contains(s) and if the number s is more than once then also index will increase and the wrong position will be saved as +1| which is wrong.
Here I am facing one more issue difference in list I am not getting the answer.
String s1 = "7 + 8 = 7 8";
String s2 = "7 + 8 = 7 + 8";
List<String> list1 = Arrays.asList(s1.split("\\s+"));
List<String> list2 = Arrays.asList(s2.split("\\s+"));
int index = 0;
for(String s : list2){
if(list1.contains(s)){
index++;
}else{
System.out.print(s+index+"|");
}
}
This function I created to find the difference, sometimes it returns the difference but sometimes it does not
public static <T> List<T> difference(List<T> answer, List<T> header) {
List<T> toReturn = new ArrayList<>(answer);
toReturn.removeAll(header);
return toReturn;
}
Your question indicates that a difference is not only defined by the elements being present in both lists but that their order matters too, i.e. 1,2,3 would be different from 3,2,1.
Hence, don't use contains() as this only reports whether one list contains an element but doesn't take the order into account.
To find positional differences, you need to compare elements at the same index. Here's a simple example of what that could look like (note that this would be inefficient when using LinkedList in which case you'd better use an iterator).
<T> int findFirstDifference(List<T> list1, List<T> list2) {
//restrict iteration to the size of the smaller list
int smallerSize = Math.min(list1.size(), list2.size());
for( int index = 0; index < smallerSize; index++) {
T e1 = list1.get(index);
T e2 = list2.get(index);
//objects are different, this is the first difference
if(!Objects.equals(e1, e2)) {
return index;
}
}
//at this point the smaller list completely matches the start of the larger list
//if there is a larger list the first difference is the index after the end of the matching portion
if( list1.size() != list2.size() ) {
return smallerSize;
}
//no difference found
return -1;
}
I have an ArrayList that contains a number of Strings, I want to be able to iterate through the ArrayLists contents searching for a string containing a semicolon. When the semicolon is found I then want to delete all of the Strings including and after the semicolon string.
So;
this, is, an, arra;ylist, string
Would become:
this, is, an
I feel like this is a very simple thing to do but for some reason (probably tiredness) I can't figure out how to do it.
Here's my code so far
public String[] removeComments(String[] lineComponents)
{
ArrayList<String> list = new ArrayList<String>(Arrays.asList(lineComponents));
int index = 0;
int listLength = list.size();
for(String str : list)
{
if(str.contains(";"))
{
}
index++;
}
return lineComponents;
}
This becomes trivial with Java 9:
public String[] removeComments(String[] lineComponents) {
return Arrays.stream(lineComponents)
.takeWhile(s -> !s.contains(";"))
.toArray(String[]::new);
}
We simply form a Stream<String> from your String[] lineComponents and take elements until we find a semicolon. It automatically excludes the element with the semicolon and everything after it. Finally, we collect it to a String[].
First of all I think you are confusing arrays and arraylists. String[] is an array of strings while ArrayList<String> is an arraylist of strings. Take into account that those are not the same and you should read Array and ArrayList documentation if needed.
Then, to solve your problem following the ArrayList approach you can go as follows. Probably it's not the optimum way to do it but it will work.
public List<String> removeComments(List<String> lineComponents, CharSequence finding)
{
ArrayList<String> aux = new ArrayList<String>();
for(String str : lineComponents)
{
if(str.contains(finding))
break;
else
aux.add(str);
}
return aux;
}
This example is just for performance and bringing back my old favorite arraycopy:
public String[] removeComments(String[] lineComponents) {
int index = -1;
for (int i = 0; i < lineComponents.length; i++) {
if ( lineComponents[i].contains(";") ) {
index = i;
break;
}
}
if (index == -1) return lineComponents;
return Arrays.copyOf(lineComponents, index);
}
I need to write a static method in a class MinTester that computes the "smallest" string
from an ArrayList collection using a comparator object:
public static String min(ArrayList<String> list, Comparator<String> comp)
I cannot use the Collections class to compute the minimum.
Here is what I have so far.
public class MinTester
{
static String least;//This is static because it is being used in a static static context
public static String min(ArrayList<String> list, Comparator<String> comp)
{
int min = 0;
for( int i = 0; i < list.size(); i++ )
{
min = list.get(i).compareTo(list.get(i++));
if(min < 0)
{
least = list.get(i);
}
else if(min == 0)
{
least = list.get(i);
}
else
{
least = list.get(i++);
}
}
return least;
}
}
I am using the min value because I read that the compareTo method returns negative, 0, or positive whether the first string is less than, equal to, or greater than the second.
I am not getting any errors here from the method, So I try to test it in Main with this.
I get this warning: "Accessing static method min"
public static void main(String[] args)
{
// TODO code application logic here
MinTester s = new MinTester();
Comparator<String> comp = null;
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("ab");
list.add("abc");
list.add("abcd");
String a = s.min(list,comp);//Warning: Accessing static method min
System.out.println(a);
}
My output from a = "abcd". Can anyone help me figure out why I am getting "abcd" as the 'Min' string in the list? I am thinking that my error is coming from my min() method, but I am not sure where inside it or why.
If you need to find the shortest String in an ArrayList without sorting it, you can simply traverse the list and check the .length attribute of every String, always keeping track of the shortest one.
String shortest = list.get(0);
for(String str : list) {
if (str.length() < shortest.length()) {
shortest = str;
}
}
System.out.println("The shortest string: " + shortest);
EDIT :
You would use Comparator if you wanted to implement custom comparison of two strings. Comparing their length can be done in 1 line, so Comparator is really not necessary. If you absolutely need to use the Comparator, you would replace
if (str.length() < shortest.length())
by
if (comp.compare(str, shortest) < 0))
it's basically the same thing, except that you don't define the comparison by yourself but leave it up to the Comparator to decide, which String of the two is smaller. This way, if you wanted the way how the strings are compared in the future, you wouldn't have to rewrite the method, you would only supply a different Comparator.
Using Streams and Comparator-
Comparator<String> comparator = (str1, str2) -> str1.length() > str2.length() ? 1 : -1;
String smallest = Arrays.stream(input)
.sorted(comparator).findFirst().get();
Reference: Find Shortest Length String
you can just use string lengths to compare and use min method of stream:
stringSet.stream().min(Comparator.comparingInt(String::length)).get();
Some pointer, using the Comparator, to get the idea. I'm not going to solve the whole problem, as this is obviously your homework (implement the Comparator for the String lengths, understand what Comparator#compareTo(T, T) returns, read the Comparator API):
public static String min(List<String> list, Comparator<String> comp) {
String shortest = null;
for (String current : list) {
if (shortest == null) { // first iteration
shortest = current;
continue;
}
int comparisonResult = comp.compare(shortest, current);
// TODO: your task; update shortest, depending on comparisonResult
}
return shortest;
}
Don't want to do all of the work for you, so I will provide a solution in Scala:
object MinTest{
def main(args: Array[String]){
val list: util.List[String] = List("a", "ab", "abc", "abcd")
val m: String = min(list, (s1, s2) => s1.length - s2.length)
println(m) //output is: a
}
def min(list: util.List[String], comp: (String, String) => Int): String = {
if(list.isEmpty)
return null
var min = list(0)
for(i <- 0 until list.size if comp(list(i), min) < 0)
min = list(i)
min
}
}
Although this is a different language, the logic is still present. It's just your responsibility to convert it to Java.
This is simple guys, cant you just create a hashmap from a list where the number in the hashmap is the length of the string then the value in the hashmap is the string that goes with that value...
Sort by the key, select item zero, then you have it , right?
What I'm saying is put all the strings in a list.. for each loop on that list, while doing so note the string in one column and the length of that string in the other "while you're there" , sort by the length, then pick the first string that goes with that length.
You can get the length of the string element using the length method
e.g. list.get(0).length()
This should return the size of the string
Good Luck
I am trying to sort integers that are in an ArrayList, that part is working but I am also trying to keep a parallel array matched with the correct integer. I can't make them into a grouped object either. So if I had 3 words with 3 numbers (Numbers in an ArrayList and words in an ArrayList ("Hello" - 2, "The" - 5, "For" - 1). I would want For and 1 to come first, then Hello and to last would be The and 5. So It would carry over the word with the number. the code I have below is sorting Integers correctly but it seems that the words are being randomized.
void quickSort2 (ArrayList<Integer> list, int first, int last, ArrayList list2){
//Set first and last
int g = first, h = last;
int midIndex, dividingValue;
//middle values
midIndex = (first + last) / 2;
dividingValue = list.get(midIndex);
System.out.println("midIdex = "+midIndex + "first = "+first+"last = "+last);
//find if higher or lower
do{
while (list.get(g) < dividingValue) {
g++;
}
while (list.get(h) > dividingValue){
h--;
}
if (g <= h){
//Switch ints (Works)
int temp = list.get(g);
list.set(g,list.get(h));
list.set(h,temp);
g++;
h--;
//Switch Strings with the ints (Doesnt work)
ArrayList blah = new ArrayList();
blah.add(list2.get(g));
list2.set(g,list2.get(h));
list2.set(h,blah.get(0));
}
}
while (g<h);
//Back to the method
if(h>first) {
quickSort2(list, first, h, list2);
}
if(g<last) {
quickSort2(list, g, last, list2);
}
}
Maybe you should try switching the Strings before you increment the values of g and h... Also you don't need to create the Arraylist blah - just get the string like you do for the int
Something like this... I haven't looked to deeply into your code but this is most likely an error...
//Switch ints (Works)
int temp = list.get(g);
list.set(g,list.get(h));
list.set(h,temp);
// *** Don't increment here ***
// *** Switch Strings with the ints first ***
String tempStr = list2.get(g);
list2.set(g,list2.get(h));
list2.set(h,tempStr );
// *** Now increment ***
g++;
h--;
Here's a simple class to group an integer key and String together:
public class DataItem {
// These are the pieces of data each DataItem will carry around
private int key;
private String data;
// This is a constructor; if you say new DataItem(2,"Hello"), it creates an
// object whose key is 2 and data is "Hello"
public DataItem(int key, String data) {
this.key = key;
this.data = data;
}
// A method to get the object's key
public int getKey() {
return key;
}
// A method to get the object's data
public String getData() {
return data;
}
}
Now your quickSort2 method will take an ArrayList<DataItem> instead of an ArrayList<Integer>. When you use the get method on the ArrayList, it will return an entire DataItem instead of just an Integer. That means that if you want the integer, you'll need to call getKey() to get it. So instead of
dividingValue = list.get(midIndex);
you'd say
dividingValue = list.get(midIndex).getKey();
and instead of
while (list.get(g) < dividingValue) {
it would be
while (list.get(g).getKey() < dividingValue) {
The good news, though, is that when you switch the items, it will switch the entire DataItem, which means the String will stay with the integer, which is what you want. So under your "Switch ints" comment, change the type of temp from int to DataItem. Then your swap will swap everything.
(To make this even better, you can have DataItem implement Comparable<DataItem>, by adding a compareTo method that will compare one DataItem to another by comparing just the key fields. Then you can use built-in sort and other methods on arrays of DataItem. I'll let you read this tutorial yourself.)
I want to get specific combination of permutation of string like alphabet. To understand me, I'll show you the code that I using:
public class PermutationExample {
public static List<String> getPermutation(String input) {
List<String> collection = null;
if (input.length() == 1) {
collection = new ArrayList<String>();
collection.add(input);
return collection;
} else {
collection = getPermutation(input.substring(1));
Character first = input.charAt(0);
List<String> result = new ArrayList<String>();
for (String str : collection) {
for (int i = 0; i < str.length(); i++) {
String item = str.substring(0, i) + first
+ str.substring(i);
result.add(item);
}
String item = str.concat(first.toString());
result.add(item);
}
return result;
}
}
public static void main(String[] args) {
System.out.println(PermutationExample.getPermutation("ABCD"));
}
}
This code works well and i can get every combination, I can take it from the list, if I need 5-th element, I can receive it. But if the string is the alphabet ... , didn't works, it's too big. What I have to do, to get the specific element like 1221-th from all 26! combinations ?
I solved a similar problem a while ago, only in python.
If what you need is simply the n-th permutation, then you can do a lot better then generating every permutation and returning the n-th, if you try to think about generating only the permutation you need.
You can do this "simply" by figuring out what should be the element in front for the number of permutations you want, and then what should be the remaining of the elements recursively.
Assume a collection of values [0, ... ,X], for any values such that col[n] < col[n+1]
For N elements, there are N! possible permutations, the case when the collection will be perfectly reversed.
We will see the change in the head of the collection after each (N-1)! permutations, so if n < (N-1)!, the head is the head. You then have a remaining number of permutations, and you can apply the same logic recursively.
Does this help? I know it's fairly high level and you'll have to think a bit about it, but maybe it'll get you on the right track.