How to find permutations for String arrays excluding own array? - java

I have the following bunch of arrays:
public class ArrayPermutationExample {
private static final String PREFIX = "ignore(FAILURE) { build(\"load\", ";
public static final String ENDING = ")}";
private static String[] arr_1 = new String[] {
"111",
"222",
"333"};
private static String[] arr_2 = new String[]{
"aaa",
"bbb",
"ccc"};
private static String[] arr_3 = new String[] {
"***",
"&&&",
"$$$"};
I need to find permutation with other arrays, excluding native array.
The output should look like:
111aaa
111bbb
111ccc
111***
111&&&
111$$$
222aaa
222bbb
222ccc
...
333aaa
333bbb
333ccc
...
Finally, for all those permutations should be added prefix and ending:
prefix permutation string endings
And at the end we should have something like:
ignore(FAILURE) { build("load", 111aaa )}
I completely stuck with a solution for this task:
private static void processArrays(String[] ... arrays) {
ArrayList<String> result = new ArrayList<>();
for (String[] array : arrays) {
String[] currentArray = array;
for (String line : currentArray) {
// exclude all lines from current array & make concatenation with every line from others
}
}
}
How to solve this issue?
UPDATE:
I want to add that finally, we need to have a distinct list without any dublications. Even following example will be duplicating each other:
111aaa***
***111aaa
I believe that this task should have a solution with Java 8 style.

I think this may be a combination since you don't actually care about getting all orderings (other than printing in the order specified by the order of the array parameters), but regardless, here is the code I wrote. I used a stack for storing unfinished arrays. Pushing to the stack each possibility at any given point for every array and pushing to results for any completed array.
public static List<String> getCombinations(String prefix, String ending, String[]... arrays) {
List<String> results = new ArrayList<>();
Stack<String[]> combinations = new Stack<>();
combinations.add(new String[arrays.length]);
while (!combinations.isEmpty()) {
String[] currentArray = combinations.pop();
if (currentArray[arrays.length - 1] == null) {
for (int i = 0; i < arrays.length; i++) {
if (currentArray[i] == null) {
for (int j = 0; j < arrays[i].length; j++) {
String[] newArray = currentArray.clone();
newArray[i] = arrays[i][j];
combinations.add(newArray);
}
break;
}
}
} else {
StringBuilder stringBuilder = new StringBuilder(prefix);
for (String string : currentArray) {
stringBuilder.append(string);
}
stringBuilder.append(ending);
results.add(stringBuilder.toString());
}
}
return results;
}
You would just need to iterate over the returned list to print out all of the strings.
As an added note, this method could be written recursively, but I usually like using a stack instead of using recursion when possible because recursion can be slow sometimes.

The way I read it: the first array arr_1 is prepended to the next 3 arrays.
I think the prefix is "ignore(FAILURE) { build("load", " and the ending is "}}"
String prefix = "ignore(FAILURE) { build(\"load\", ";
String ending = "}}";
for (String first: arr_1) {
for (String second: arr_2) {
System.out.println( prefix + first + second + ending);
}
for (String second: arr_3) {
System.out.println( prefix + first + second + ending);
}
for (String second: arr_4) {
System.out.println( prefix + first + second + ending);
}
}

Related

Text to string array and delete duplicates

The idea of the program is that it gets the text divided by space from the scanner.
I need to write a method to create an array from text, delete duplicates and return an array of the words which are used only once and don't have duplicates.
I can't find out how to make a new array of unique words. Using only simple and basic construction without HashSet etc.*
For example:
a b a b c a b d
result:
c d
public static String Dublicate(String text) {
String[] dublic = text.split(" ");
String result="";
for (int i = 0; i < dublic.length; i++) {
for (int j = i + 1; j < dublic.length; j++)
if (dublic[i].equals(dublic[j]))
dublic[j] = "delete";
}
for (String s: dublic) {
if (s !="delete") {
result =result + s + " ";
}
}
return result;
}
Split By Space
For splitting by space we can use the split() method & can pass the Space string ("") in the parameter.
String[] texts = text.split(" ");
Delete The duplicate elements
If We can use java 1.8 or greater than 1.8, we can use stream API for getting distinct elements like.
Arrays.stream(texts).distinct().toArray(String[]::new);
Or if we need to implement it with java 1.7, we can use HashSet for getting distinct elements like.
String[] distinctElements = new HashSet<String>(Arrays.asList(texts)).toArray(new String[0]);
The final Source code can be like this:
public static String[] textToArray1_7(String text) {
//split by space
String[] texts = text.split(" ");
//Distinct value
return Arrays.stream(texts).distinct().toArray(String[]::new);
}
public static String[] textToArray1_8(String text) {
//split by space
String[] texts = text.split(" ");
//Distinct value
return new HashSet<String>(Arrays.asList(texts)).toArray(new String[0]);
}
If any further question, can ask for more clarification.
You forgot to mark i-th element as duplicate in case when it really is. See my comments in the below code
public static String Dublicate(String text) {
String[] dublic = text.split(" ");
String result="";
for (int i=0; i<dublic.length; i++){
if (dublic[i].equals("delete")) { // Minor optimization:
// skip elements that are already marked
continue;
}
boolean isDub = false; // we need to track i-th element
for(int j=i+1; j<dublic.length; j++) {
if (dublic[i].equals(dublic[j])) {
dublic[j] = "delete";
isDub = true; // i-th element is also a duplicate...
}
}
if (isDub) {
dublic[i] = "delete"; // ...so you should also mark it
}
}
for(String s: dublic){
if(!s.equals("delete")) { // for strings you should use "!equals" instead of "!="
result = result + s + " ";
}
}
return result;
}
P.S. if original text contains "delete" the result will be incorrect since you use "delete" as a reserved marker word
If the array of unique strings needs to be returned, then the initial array of strings after the splitting the input has to be compacted to exclude invalid values, and a smaller copy needs to be returned:
public static String[] uniques(String text) {
String[] words = text.split(" ");
int p = 0; // index/counter of unique elements
for (int i = 0; i < words.length; i++) {
String curr = words[i];
if (null == curr) {
continue;
}
boolean dupFound = false;
for (int j = i + 1; j < words.length; j++) {
if (null == words[j]) {
continue;
}
if (curr.equals(words[j])) {
words[j] = null;
dupFound = true;
}
}
if (dupFound) {
words[i] = null;
} else {
words[p++] = words[i]; // shift unique elements to the start of array
}
}
return Arrays.copyOf(words, p);
}
If the array of unique strings is returned, it may be conveniently converted into String using String::join as shown below in the test.
Test:
System.out.println(Arrays.toString(uniques("a b a b c a b d")));
System.out.println(String.join(" ", uniques("a b a b c a b d")));
Output
[c, d]
c d

Generate word combinations from a list of strings in java

I wanted to create an algorithm in java where I can pass a list of strings and it returns a new list with all possible combinations of the strings it has in the list.
Example:
String[] listWords = new String[] {
"windows",
"linux",
"mac",
"10",
"20"
};
I would like to call a method by passing the list that returns all possible combinations, in all orders.
combinations(listWords);
This is the result I wanted to have:
windows,linux,mac,10,20,windowslinux,linuxwindows,windowsmac,windows10,10windows,windows20,20windows,windowslinuxmac1020,windowsmaclinux20,mac10,mac20,20mac,20mac10,windowsmac,macwindows...
I tried this:
public String[][] combinations (String[] ports) {
List<String[]> combinationList = new ArrayList<String[]>();
for ( long i = 1; i < Math.pow(2, ports.length); i++ ) {
List<String> portList = new ArrayList<String>();
for ( int j = 0; j < ports.length; j++ ) {
if ( (i & (long) Math.pow(2, j)) > 0 ) {
portList.add(ports[j]);
}
}
combinationList.add(portList.toArray(new String[0]));
}
return combinationList.toArray(new String[0][0]);
}
But this returns:
This was not how I wanted it. The result had to be:
list: [windows, linux, windowslinux, linuxwindows, windows10, 10windowsmaclinux...]
Is it possible to do this in java? thank you who can help :)
If I've understood you correctly, the following will solve the problem.
You can build the result iteratively starting from the list of words that you have, and in each iteration you add longer and longer words. The first iteration gives you the original list. The second iteration adds one new word to each, giving you the permutations of 2 words. The third iteration adds one new word to each of those, giving you the permutations of 3 words, and so on.
List<String> getWordPermutations(List<String> words) {
List<String> result = new ArrayList<>(words);
List<String> oldPermutations = new ArrayList<>(words);
for (int i = 1; i < words.size(); i++) {
List<String> newPermutations = new ArrayList<>();
for (String previousList : oldPermutations) {
for (String word : words) {
if (previousList.contains(word)) {
continue;
}
newPermutations.add(previousList + word);
}
}
oldPermutations = newPermutations;
result.addAll(newPermutations);
}
return result;
}

Java checking if an element from a list appears in all occurrences

I have a method that takes in an ArrayList of strings with each element in the list equaling to a variation of:
>AX018718 Equine influenza virus H3N8 // 4 (HA)
CAAAAGCAGGGTGACAAAAACATGATGGATTCCAACACTGTGTCAAGCTTTCAGGTAGACTGTTTTCTTT
GGCATGTCCGCAAACGATTTGCAGACCAAGAACTGGGTGATGCCCCATTCCTTGACCGGCTTCGCCGAGA
This method is broken down into the Acc, which is AX018718 in this case and seq which are the two lines following the Acc
This is then checked by another ArrayList of strings called pal to see if the substrings match [AAAATTTT, AAACGTTT, AAATATATTT]
I am able to get all of the matches for the different elements of the first list outputted as:
AATATATT in organism: AX225014 Was found in position: 15 and at 15
AATATT in organism: AX225014 Was found in position: 1432 and at 1432
AATATT in organism: AX225016 Was found in position: 1404 and at 1404
AATT in organism: AX225016 Was found in position: 169 and at 2205
Is it possible to check if for all of the outputted information if all of the Acc match one pal?
In the case above, the wanted output would be:
AATATT was found in all of the Acc.
my working code:
public static ArrayList<String> PB2Scan(ArrayList<String> Pal) throws FileNotFoundException, IOException
{
ArrayList<String> PalindromesSpotted = new ArrayList<String>();
File file = new File("IAV_PB2_32640.txt");
Scanner sc = new Scanner(file);
sc.useDelimiter(">");
//initializes the ArrayList
ArrayList<String> Gene1 = new ArrayList<String>();
//initializes the writer
FileWriter fileWriter = new FileWriter("PB2out");
PrintWriter printwriter = new PrintWriter(fileWriter);
//Loads the Array List
while(sc.hasNext()) Gene1.add(sc.next());
for(int i = 0; i < Gene1.size(); i++)
{
//Acc breaks down the title so the element:
//>AX225014 Equine influenza virus H3N8 // 1 (PB2)
//ATGAAGACAACCATTATTTTGATACTACTGACCCATTGGGTCTACAGTCAAAACCCAACCAGTGGCAACA
//GGCATGTCCGCAAACGATTTGCAGACCAAGAACTGGGTGATGCCCCATTCCTTGACCGGCTTCGCCGAGA
//comes out as AX225014
String Acc = Accession(Gene1.get(i));
//seq takes the same element as above and returns only
//ATGAAGACAACCATTATTTTGATACTACTGACCCATTGGGTCTACAGTCAAAACCCAACCAGTGGCAACA
//GGCATGTCCGCAAACGATTTGCAGACCAAGAACTGGGTGATGCCCCATTCCTTGACCGGCTTCGCCGAGA
String seq = trimHeader(Gene1.get(i));
for(int x = 0; x<Pal.size(); x++)
{
if(seq.contains(Pal.get(x))){
String match = (Pal.get(x) + " in organism: " + Acc + " Was found in position: "+ seq.indexOf(Pal.get(x)) + " and at " +seq.lastIndexOf(Pal.get(x)));
printwriter.println(match);
PalindromesSpotted.add(match);
}
}
}
Collections.sort(PalindromesSpotted);
return PalindromesSpotted;
}
First off, your code won't write to any file to log the results since you don't close your writers or at the very least flush PrintWriter. As a matter of fact you don't close your reader as well. You really should close your Readers and Writers to free resources. Food for thought.
You can make your PB2Scan() method return either a simple result list as it does now, or a result list of just acc's which contain the same Pal(s), or perhaps both where a simple result list is logged and at the end of that list a list of acc's which contain the same Pal(s) which will also be logged.
Some additional code and an additional integer parameter for the PB2Scan() method would do this. For the additional parameter you might want to add something like this:
public static ArrayList<String> PB2Scan(ArrayList<String> Pal, int resultType)
throws FileNotFoundException, IOException
{ .... }
Where the integer resultType argument would take one of three integer values from 0 to 2:
0 - Simple result list as the code currently does now;
1 - Acc's that match Pal's;
2 - Simple result list and Acc's that Match Pal's at the end of result list.
You should also really have the file to read as an argument for the PB2Scan() method since this file could very easily be a different name the next go around. This makes the method more versatile rather than if the name of the file was hard-coded.
public static ArrayList<String> PB2Scan(String filePath, ArrayList<String> Pal, int resultType)
throws FileNotFoundException, IOException { .... }
The method can always write the Same output file since it would best suit what method it came from.
Using the above concept rather than writing to the output file (PB2Out.txt) as the PalindromesSpotted ArrayList is being created I think it's best to write the file after your ArrayList or ArrayLists are complete. To do this another method (writeListToFile()) is best suited to carry out the task. To find out if any same Pal's match other Acc's it is again a good idea to have yet another method (getPalMatches()) do that task.
Since the index locations of of more than one given Pal in any given Seq was not reporting properly either I have provided yet another method (findSubstringIndexes()) to quickly take care of that task.
It should be noted that the code below assumes that the Seq acquired from the trimHeader() method is all one single String with no Line Break characters within it.
The reworked PB2Scan() method and the other above mentioned methods are listed below:
The PB2Scan() Method:
public static ArrayList<String> PB2Scan(String filePath, ArrayList<String> Pal, int resultType)
throws FileNotFoundException, IOException {
// Make sure the supplied result type is either
// 0, 1, or 2. If not then default to 0.
if (resultType < 0 || resultType > 2) {
resultType = 0;
}
ArrayList<String> PalindromesSpotted = new ArrayList<>();
File file = new File(filePath);
Scanner sc = new Scanner(file);
sc.useDelimiter(">");
//initializes the ArrayList
ArrayList<String> Gene1 = new ArrayList<>();
//Loads the Array List
while (sc.hasNext()) {
Gene1.add(sc.next());
}
sc.close(); // Close the read in text file.
for (int i = 0; i < Gene1.size(); i++) {
//Acc breaks down the title so the element:
//>AX225014 Equine influenza virus H3N8 // 1 (PB2)
//ATGAAGACAACCATTATTTTGATACTACTGACCCATTGGGTCTACAGTCAAAACCCAACCAGTGGCAACA
//GGCATGTCCGCAAACGATTTGCAGACCAAGAACTGGGTGATGCCCCATTCCTTGACCGGCTTCGCCGAGA
//comes out as AX225014
String Acc = Accession(Gene1.get(i));
//seq takes the same element as above and returns only
//ATGAAGACAACCATTATTTTGATACTACTGACCCATTGGGTCTACAGTCAAAACCCAACCAGTGGCAACA
//GGCATGTCCGCAAACGATTTGCAGACCAAGAACTGGGTGATGCCCCATTCCTTGACCGGCTTCGCCGAGA
String seq = trimHeader(Gene1.get(i));
for (int x = 0; x < Pal.size(); x++) {
if (seq.contains(Pal.get(x))) {
String match = Pal.get(x) + " in organism: " + Acc +
" Was found in position(s): " +
findSubstringIndexes(seq, Pal.get(x));
PalindromesSpotted.add(match);
}
}
}
// If there is nothing to work with get outta here.
if (PalindromesSpotted.isEmpty()) {
return PalindromesSpotted;
}
// Sort the ArrayList
Collections.sort(PalindromesSpotted);
// Another ArrayList for matching Pal's to Acc's
ArrayList<String> accMatchingPal = new ArrayList<>();
switch (resultType) {
case 0: // if resultType is 0 is supplied
writeListToFile("PB2Out.txt", PalindromesSpotted);
return PalindromesSpotted;
case 1: // if resultType is 1 is supplied
accMatchingPal = getPalMatches(PalindromesSpotted);
writeListToFile("PB2Out.txt", accMatchingPal);
return accMatchingPal;
default: // if resultType is 2 is supplied
accMatchingPal = getPalMatches(PalindromesSpotted);
ArrayList<String> fullList = new ArrayList<>();
fullList.addAll(PalindromesSpotted);
// Create a Underline made of = signs in the list.
fullList.add(String.join("", Collections.nCopies(70, "=")));
fullList.addAll(accMatchingPal);
writeListToFile("PB2Out.txt", fullList);
return fullList;
}
}
The findSubstringIndexes() Method:
private static String findSubstringIndexes(String inputString, String stringToFind){
String indexes = "";
int index = inputString.indexOf(stringToFind);
while (index >= 0){
indexes+= (indexes.equals("")) ? String.valueOf(index) : ", " + String.valueOf(index);
index = inputString.indexOf(stringToFind, index + stringToFind.length()) ;
}
return indexes;
}
The getPalMatches() Method:
private static ArrayList<String> getPalMatches(ArrayList<String> Palindromes) {
ArrayList<String> accMatching = new ArrayList<>();
for (int i = 0; i < Palindromes.size(); i++) {
String matches = "";
String[] split1 = Palindromes.get(i).split("\\s+");
String pal1 = split1[0];
// Make sure the current Pal hasn't already been listed.
boolean alreadyListed = false;
for (int there = 0; there < accMatching.size(); there++) {
String[] th = accMatching.get(there).split("\\s+");
if (th[0].equals(pal1)) {
alreadyListed = true;
break;
}
}
if (alreadyListed) { continue; }
for (int j = 0; j < Palindromes.size(); j++) {
String[] split2 = Palindromes.get(j).split("\\s+");
String pal2 = split2[0];
if (pal1.equals(pal2)) {
// Using Ternary Operator to build the matches string
matches+= (matches.equals("")) ? pal1 + " was found in the following Accessions: "
+ split2[3] : ", " + split2[3];
}
}
if (!matches.equals("")) {
accMatching.add(matches);
}
}
return accMatching;
}
The writeListToFile() Method:
private static void writeListToFile(String filePath, ArrayList<String> list, boolean... appendToFile) {
boolean appendFile = false;
if (appendToFile.length > 0) { appendFile = appendToFile[0]; }
try {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath, appendFile))) {
for (int i = 0; i < list.size(); i++) {
bw.append(list.get(i) + System.lineSeparator());
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
You should probably create aMap<String, List<String>> containing the Pals as keys and the Accs that contain them as values.
Map<String, List<String>> result = new HashMap<>();
for (String gene : Gene1) {
List<String> list = new ArrayList<>();
result.put(gene, list);
for (String pal : Pal) {
if (acc.contains(trimHeader(gene))) {
list.add(pal);
}
}
}
Now you have a Map that you can query for the Pals every Gene contains:
List<String> containedPals = result.get(gene);
This is a very reasonable result for a function like this. What you do afterwards (ie the writing into a file) should better be done in another function (that calls this one).
So, this is probably what you want to do:
List<String> genes = loadGenes(geneFile);
List<String> pals = loadPal(palFile);
Map<String, List<String>> genesToContainedPal = methodAbove(genes, pals);
switch (resultTyp) {
// ...
}

Java : Compare previous record with current record in arraylist

I have a sorted array list with 6 elements.The first 5 elements have some value, and the 6th one is empty.
I want to loop through this ArrayList, and compare the first 5 elements of first record, with the same elements in next record. If any one of the element is different, then populate 6th element.
Anyone know an easier and faster approach to do that?
Thanks
Angad
First split the all records into many String[], then parse all values in each. After that you can compare the current record with the first one. Here is an example:
public class StringComparison {
ArrayList<String[]> list = new ArrayList<String[]>();
public void comapreStrings() {
// The list you are comparing everything to
String[] firstRecord = list.get(0);
for(int n = 1; n < list.size(); n++) {
String[] currentRecord = list.get(n);
for (int i = 0; i < currentRecord.length; i++) {
String val1 = firstRecord[i];
String val2 = currentRecord[i];
if (val1.equals(val2)) {
// The two strings are the same
} else {
// Replace "a value" with whatever you want to fill the 6th element with
currentRecord[5] = "a value";
}
}
}
}
Maybe this could be an alternative to think about:
public String[] generateFirstRow(int startingRow) {
final String[] row1 = rowList.get(startingRow);
final String[] row2 = rowList.get(startingRow + 1);
final List<String> list1 = Arrays.stream(row1).collect(toList());
final List<String> toAdd = Arrays.stream(row2).parallel().sorted().filter(s -> !list1.contains(s)).collect(Collectors.toList());
if (list1.get(list1.size() - 1) == "") {
list1.set(list1.size() - 1, toAdd.get(0));
return list1.toArray(new String[0]);
}
return new String[0];
}
Now you can call this per row you have untill the pre-last one.

Merging values of 2 string arrays in one concatenated strings array

I have 2 string arrays.
string [] first = {"ajunkbc","ajunkHello","adedbc","abcjunk","add","ad","a","","junk","ajunk","aajunkbb"};
String [] second = {"abc","aHello","adedbc","abcjunk","add","ad","a","","junk","a","aajunkbb"};
I'd like the result of my merge() method to concatenate each element from the first array with the respective element of the second array separated by a comma.
Below is my code
private static String[] merge(String [] tests, String [] expectations){
List<String> testList = Arrays.asList(tests);
List<String> expectationsList = Arrays.asList(expectations);
List<String> retList = new ArrayList<String>();
for(String test : testList){
for(String val : expectationsList){
retList.add(test+","+val);
break;
}
}
This does not work. What's wrong with my code?
What's wrong is that you are looping over expectationsList and breaking out of the loop after the first iteration:
for(String val : expectationsList){
retList.add(test+","+val);
break; //<--- breaking out of loop after first iteration each time
}
So the result is that you are always retrieving the first element of expectationsList.
Since what you want is to loop over two arrays, you should use an index:
for (int i = 0; i < testList.size(); i++) {
retList.add(testList.get(i)+","+expectationsList.get(i));
}
Also, note that this implies that the size of testList is the same as the size of expectationsList. Your method should probably throw an exception if this is not the case.
Note that you do not need to convert the input arrays into lists. You can use them as-is.
private static String[] merge(String[] tests, String[] expectations) {
if (tests.length != expectations.length) {
throw new IllegalArgumentException("input not of same length");
}
String[] result = new String[tests.length];
for (int i = 0; i < tests.length; i++) {
result[i] = tests[i] + "," + expectations[i]);
}
return result;
}
Java 8 solution:
private static String[] merge(String[] tests, String[] expectations) {
if (tests.length != expectations.length) {
throw new IllegalArgumentException("input not of same length");
}
return IntStream.range(0, tests.length).mapToObj(i -> tests[i] + "," + expectations[i]).toArray(String[]::new);
}
You're iterating through each member of testList and then for each one, iterating through each member of expectationsList. You want to iterate through each of both of them together.
What you want to do is something like this:
private static String[] merge(String[] tests, String[] expectations) {
String[] result = new String[tests.length];
for(int i = 0; i < tests.length; i++) {
result[i] = tests[i] + "," + expectations[i];
}
return result;
}
This code makes the assumption that tests and expectations have the same length. You might want to do a check for that at the beginning:
if (tests.length != expectations.length) {
throw new IllegalArgumentException("tests and expectations are of different lengths")
}
Notice how now you're getting the element at the same index from both arrays.
Sidenote: You can iterate over arrays with the for each format. This works just fine:
String[] myStringArray = getStringArray();
for (String myString : myStringArray) {
// Do something
}
You don't need to convert to a List in order to iterate :)

Categories