Generation of all subsets of strings for a given string - java

I want a code to generate all the subsets of strings of the given string.
I tried this on my own and came up with this :
public static void main(String[] args){
long startTime = System.nanoTime();
String text = "1234";
int n = text.length();
String k = "";
for(int i=0;i < Math.pow(2, n);i++){
k = Integer.toBinaryString(i);
while(k.length() != n){
k = "0"+k;
}
StringBuilder sb = new StringBuilder();
for(int j=0;j<k.length();j++){
if(k.charAt(j) == '1'){
sb.append(text.charAt(j));
}
}
// System.out.println(String.format("%04d",
// Integer.parseInt(k)));
System.out.println(sb.toString());
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println("Duration:" + duration);
}
But this is a horrible O(n^2) algorithm so I was looking for a better solution and found this:
public static void comb2(String s) {
comb2("", s);
}
private static void comb2(String prefix, String s) {
System.out.println(prefix);
for (int i = 0; i < s.length(); i++){
comb2(prefix + s.charAt(i), s.substring(i + 1));
}
}
// read in N from command line, and print all subsets among N elements
public static void main(String[] args) {
String alphabet = "1234";
comb2(alphabet);
System.out.println();
}
The output generated is :
1
12
123
1234
124
13
134
14
2
23
234
24
3
34
4
Although the code is working fine. I was debugging it to understand the logic. I get how 1, 12, 123, 1234 are being generated but after that is not so clear. Can tell me whats going on here?

What you need to understand is how the comb2 method works. Basically, it calls itself. This is called recursion.
When you call comb2("1234"), the result is a call to comb2("","1234").
comb2("","1234") prints "" (which has no effect), then starts a loop
through the end of the string ("234"). The first thing it does in
this loop is call comb2("1","234").
comb2("1", "234") prints "1", then starts a loop through the end of
the string ("234"). The first thing it does in this loop is call
comb2("12","34").
comb2("12", "34") prints "12", then starts a loop through the end of
the string ("34"). The first thing it does in this loop is call
comb2("123","4").
comb2("123", "4") prints "123", then starts a loop through the end of
the string ("4"). The first thing it does in this loop is call
comb2("1234","").
comb2("1234", "") prints "1234", then starts a loop through the end
of the string (""). Since there is nothing to do, it returns
immediately to its caller : comb2("123","4").
comb2("123", "4") now goes to the next step in its loop. Since there
is none, it returns.
comb2("12", "34") now goes to the next step in its loop. It calls
comb2("124","").
comb2("124", "") prints "124", then starts a loop through the end of
the string (""). There is nothing to do, so it returns immediately.
This is how you get from "1234" to "124". Hopefully, from there, you shoud be able to understand the whole execution.

The key point is comb2(prefix + s.charAt(i), s.substring(i + 1)), to understand it better please build an analogy from this statement with the cartesian product, I think this solves every thing. Indeed your'e creating all substrings starting the prefix.

This program should work correctly
public static void getAllSubStrings(char[] chars,int start, Set allSubStrings){
StringBuilder sb = new StringBuilder();
if(start==chars.length){
return;
}
for(int i=start;i<chars.length;i++){
sb.append(chars[i]);
allSubStrings.add(sb.toString());
}
getAllSubStrings(chars, start+1, allSubStrings);
}
public static void main(String[] args) {
Set s = new TreeSet();
getAllSubStrings("12345".toCharArray(), 0, s);
System.out.println(s);
}
Generated output is [1, 12, 123, 1234, 12345, 2, 23, 234, 2345, 3, 34, 345, 4, 45, 5]
From what I think this is still going to be O(n2) because it will run n+(n-1)+(n-2)... times which is n(n+1)/2 I don't think you can get better than that

Here's what a moment's noodling brought me:
import java.util.List;
import java.util.LinkedList;
public class subs {
static List<String> allInitialSubstrings(String s) {
List<String> r = new LinkedList<String>();
for (int i=0; i<s.length(); i++) {
r.add(s.substring(0, i+1));
}
return r;
}
static List<String> allSubstrings(String s) {
List<String> r = new LinkedList<String>();
for (int i=0; i<s.length(); i++) {
r.addAll(allInitialSubstrings(s.substring(i)));
}
return r;
}
public static void main(String ... args) {
System.out.println(allSubstrings(args[0]));
}
}
~ $ javac subs.java
~ $ java subs 12345
[1, 12, 123, 1234, 12345, 2, 23, 234, 2345, 3, 34, 345, 4, 45, 5]
If you want subsets instead of substrings, it's too much a pain in the neck for me to write it in an archaic language like Java, but here it is in the only-slightly elderly Python:
def allSubsets(s):
if len(s):
car = s[0]
cdr = allSubsets(s[1:])
return set([car + b for b in cdr]).union(cdr)
else:
return set([""])
allSubsets("12345")

Without any for loop, cleaner version with same logic would be:
public static void printSubSets(String s){
subSetsHelper(s, "");
}
private static void subSetsHelper(String s, String acc) {
if (s.equals("")){
System.out.println(acc);
return;
}
subSetsHelper(s.substring(1), acc + s.charAt(0)); // accumulate 1st character
subSetsHelper(s.substring(1), acc); // do not
}
printSubSets("abc");
abc
ab
ac
a
bc
b
c
""

Related

Print number of possible non-empty sequences of letters

I want to print number of possible non-empty sequences of letters .
Eg.
String str="ABC";
Expected output is
A,B,C
AB,AC,BC,BA,CA,CB
ABC,ACB,BAC,BCA,CAB,CBA`
But i get the below output which is incorrect. How to fix my code
BB CC A AB ACC BC ABC AC B BBC CCC BCC C CBC CB
I have written the below code using Recurion
String tiles = "ABC";
Set<String> ans = new HashSet<>();
solve(tiles, 0, "", ans);
public static void solve(String tiles, int idx, String output, Set<String> ans) {
ans.add(output);
if (idx >= tiles.length()) {
return;
}
for (int i = idx; i < tiles.length(); i++) {
solve(tiles, idx + 1, output + tiles.charAt(i), ans);
}
}
This is how recursion tree would look like for str="AAB"
You need to ignore the first passing of the "" from output and then you need to ignore each letter you already passed through
public static void main(String[] args) {
String tiles = "ABC";
List<String> ans = new ArrayList<>();
solve(tiles, "", ans);
System.out.println(ans);
}
public static void solve(String tiles, String output, List<String> ans) {
if (!output.equals("")) ans.add(output);
for (int i = 0; i < tiles.length(); i++) {
String str = tiles.substring(0, i) + tiles.substring(i + 1);
solve(str, output + tiles.charAt(i), ans);
}
}
Output
[A, AB, ABC, AC, ACB, B, BA, BAC, BC, BCA, C, CA, CAB, CB, CBA]
you can try this
public class Permutation {
public static List<String> getPermutations(String str) {
Set<String> permutations = new HashSet<>();
permute(str, "", permutations);
return new ArrayList<>(permutations);
}
private static void permute(String string, String prefix, Set<String> permutations) {
if (string.length() == 0) {
permutations.add(prefix);
} else {
for (int i = 0; i < string.length(); i++) {
char charAt = string.charAt(i);
String remainingString = string.substring(0, i) + string.substring(i + 1);
permute(remainingString, prefix + charAt, permutations);
}
}
}
}
The "permute" method takes in 3 parameters: a string, a prefix string and a set of permutations.
The "permute" method takes in 3 parameters: a string, a prefix string and a set of permutations.
If the input string is not empty, it uses a for loop to iterate through the characters of the input string.
For each iteration, it gets the character at the current index, creates a new string by removing that character from the input string.
it then calls the permute method 3 times:
it then calls the permute method 3 times:
One with the original string and prefix
One with the remaining string and prefix
This way, the function explores all the possible permutations of the characters in the input string, including the option of not having one of the characters in the permutation and the permutation of positions, without including an empty string as an option.
Then you use like:
Permutation p = new Permutation();
List<String> permutations = p.getPermutations("abc");
Make 1 change:
Set<String> ans = new TreeSet<>(Comparators.comparing(String::length).thenComparing(s -> s));
It's a quite popular backtracking problem. You can find almost same problem here:
https://leetcode.com/problems/subsets/
The input are numbers instead of characters but the idea is the same.
You can switch to the solution tab and explore different answers:
https://leetcode.com/problems/subsets/solutions/

Get string and store certain types of characters in arraylists

I'm pretty much a beginner in java and I can't figure out how to do this, even after googling.
So, I'm making a basic calculator that will get a string from the user, and store it's values... (I don't even know how to explain this)
For example: the input of the user is "5+3-6*2"... I want to store in the list the 5,3,6 and 2, and the symbols of operations in another in the order they have been typed...(then I'll try to figure how to execute the operations in order, but that's not this question).
How can I do that?
Here is a simple way to solve your problem, i used one list to store every thing after i just separate the numbers and the operator in two list
1st put the first char in the list:
2ed iteration test if the president value size - 1 is a number
if it is a number then (oldNumber*10) + newNumber
That's it
this should help you:
public static void main(String args[]) {
String operation = "55*6-66-33+15/99";
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < operation.length(); i++) {
if (!list.isEmpty()) {
if (operation.charAt(i) >= '0' && operation.charAt(i) <= '9') {
String str = list.get(list.size() - 1);
if (testInteger(str)) {
int d = Integer.parseInt(str);
int d2 = Integer.parseInt(operation.charAt(i) + "");
String s = (d * 10 + d2) + "";
list.set(list.size() - 1, s);
} else {
list.add(operation.charAt(i) + "");
}
} else {
list.add(operation.charAt(i) + "");
}
} else {
list.add(operation.charAt(i) + "");
}
}
Now you can separate your numbers and operations in two Lists
List<Integer> listNumber = new ArrayList<>();
List<String> listOperation = new ArrayList<>();
for (String s : list) {
if (testInteger(s)) {
listNumber.add(Integer.parseInt(s));
} else {
listOperation.add(s);
}
}
System.out.println(listNumber);
System.out.println(listOperation);
}
This methode test if the chat is a number or not:
private static boolean testInteger(String str) {
try {
int d = Integer.parseInt(str);
} catch (NumberFormatException e) {
return false;
}
return true;
}
The result should be like this:
Principal list = [55, *, 6, -, 66, -, 33, +, 15, /, 99]
List of numbers = [55, 6, 66, 33, 15, 99]
List of operations = [*, -, -, +, /]
You can minimize the code if you want, but this can give you and idea.
ArrayList<Character> nums = new ArrayList<>();
ArrayList<Character> ops = new ArrayList<>();
for (int i = 0; i < expression.length(); ++i) {
char c = expression.charAt(i);
if (c >= '0' && c <= '9') nums.add(c);
else ops.add(c);
}
Anything more complicated and you'll need to look into parsers or regexes
I'd also like to point out that this is assuming each number is 1 digit as in your example.

How can I find all recursive combinations of different size Strings in an ArrayList? - See example

Clearly, that is almost impossible to understand.
So, here is an example:
If I have an ArrayList = ["abc", "def"]
Then the result I desire is:
ad ae af
bd be bf
cd ce cf
And the same can be assumed if I have an ArrayList = ["ab", "cd", "efg"]:
ace acf acg
ade adf adg
bce bcf bcg
bde bdf bdg
Where all the options are shown. The first index String corresponds to the first 'potential' letter of the result. The second corresponds with the second, and so forth. I have been looking into different forms of recursion, but I seem to have run into a hole. Here is what I have so far:
public static void main(String[] args) {
ArrayList<String> param = new ArrayList<String>();
param.add("jkl");
param.add("mno");
param.add("pqrs");
System.out.println(giveFrag(param, 0));
}
static String giveLetter(String s, int indexForString) {
// return the letter given
return s.substring(indexForString, indexForString+1);
}
static String giveFrag(ArrayList<String> strs, int start) {
String output = "";
if (start == strs.size()-1) {
output = giveLetter(strs.get(start),0);
} else {
for (int i = 0; i < strs.get(start).length(); i++) {
String q = strs.get(start).substring(i,i+1);
output += q;
for (int k = strs.size()-1; k < strs.size(); k++) {
output += giveFrag(strs, start+1);
}
output += " ";
}
output += "\n";
}
return output;
}
NOTICE THAT FOR SIMPLICITY'S SAKE, I IGNORE THE LAST ELEMENT OF THE ARRAYLIST. THIS CAN BE SEEN IN THE IF STATEMENT OF giveFrag().
Currently, my result is as follows:
jmp np op
kmp np op
lmp np op
Now, to the actual question! First of all, if anyone spots any glaring errors that would produce this result instead of:
jmp jnp jop
kmp knp kop
lmp lnp lop
Please let me know. If there aren't any obvious ones, and an entire restructure is needed, could you please be very specific for what I should be doing instead?
In addition, if anyone has any additional time on their hands, could they find a way to include the last array element when iterating?
Thanks so much for your help, and sorry for the incredibly vague title.
The current output doesn't match the description of the problem.
The first line of the output should be:
jmp jmq jmr jms
The implementation is not really close to what you need.
Consider this instead:
private void accumulateFrags(List<String> strings, int start, String prefix, List<String> frags) {
if (start == strings.size()) {
frags.add(prefix);
return;
}
String current = strings.get(start);
for (char c : current.toCharArray()) {
accumulateFrags(strings, start + 1, prefix + c, frags);
}
}
This function will accumulate all combinations in a list.
Call it like this:
List<String> frags = new ArrayList<>();
accumulateFrags(Arrays.asList("jkl", "mno", "pqrs"), 0, "", frags);
System.out.println(frags);
This doesn't produce the line by line output you desire.
But that should be fairly straightforward to do,
so I leave that as an exercise for you.
recursive
// arguments are passed using the text field below this editor
public static void main(String[] args)
{
String arr[] = {"jkl", "mno", "pqrs"};
List<String> res = new ArrayList<String>();
constructStr(res, "", 0, arr);
String s = "";
for (int i=0; i<res.size(); i++) {
int mod = arr[arr.length-1].length();
if (i % mod == 0) {
System.out.println(s);
s = res.get(i) + " ";
}
else {
s += res.get(i) + " ";
}
}
System.out.println(s);
}
private static void constructStr(List<String> result, String curStr, int i, String arr[]) {
if (i + 1 < arr.length) {
for (int k=0; k<arr[i].length(); k++) {
constructStr(result, curStr + arr[i].charAt(k), i + 1, arr);
}
}
else {
for (int k=0; k<arr[i].length(); k++) {
result.add(curStr + arr[i].charAt(k));
}
}
}

How would I split this expression with regex?

I'm working on solving an equation but I will like to use the constants to program my solution.
The method I'm working on is called decompose which decomposes the equation into constants. The problem is that when I split, an equation with a negative constant will yield an array with the absolute value of the constants. How can I achieve the minus sign while still using regex?
If the input is ax+by=c, the output should be {a,b,c}.
Helpful bonus: Is there a way to delete the empty elements that is created when I split. For example, if I type equation 2x+3y=6, I end up with a "raw" array that contains the elements {2,,3,,6}
Code:
public static int[] decompose(String s)
{
s = s.replaceAll(" ", "");
String[] termRaw = s.split("\\D"); //Splits the equation into constants *and* empty spaces.
ArrayList<Integer> constants = new ArrayList<Integer>(); //Values are placed into here if they are integers.
for(int k = 0 ; k < termRaw.length ; k++)
{
if(!(termRaw[k].equals("")))
{
constants.add(Integer.parseInt(termRaw[k]));
}
}
int[] ans = new int[constants.size()];
for(int k = 0 ; k < constants.size(); k++) //ArrayList to int[]
{
ans[k] = constants.get(k);
}
return ans;
}
The general strategy to this answer is to split the input equation by operator, then extract out the coefficients in a loop. However, there are several edge cases which need to be considered:
a plus symbol (+) is prefixed to every minus which does not appear either as the first term
after splitting, a coefficient of positive one is detected by seeing empty string
after splitting, a coefficient of negative one is detected by seeing a minus sign
String input = "-22x-77y+z=-88-10+33z-q";
input = input.replaceAll(" ", "") // remove whitespace
.replaceAll("=-", "-"); // remove equals sign
.replaceAll("(?<!^)-", "+-"); // replace - with +-, except at start of line
// input = -22x+-77y+z+-88+-10+33z+-
String[] termRaw = bozo.split("[\\+*/=]");
// termRaw contains [-22x, -77y, z, -88, -10, 33z, -]
ArrayList<Integer> constants = new ArrayList<Integer>();
// after splitting,
// termRaw contains [-22, -77, '', -88, -10, 33, '-']
for (int k=0 ; k < termRaw.length ; k++) {
termRaw[k] = termRaw[k].replaceAll("[a-zA-Z]", "");
if (termRaw[k].equals("")) {
constants.add(1);
}
else if (termRaw[k].equals("-")) {
constants.add(-1);
}
else {
constants.add(Integer.parseInt(termRaw[k]));
}
}
If you're using java8, then you can use this one line method:
public static int[] decompose(String s) {
return Arrays.stream(s.replaceAll("[^0-9]", " ").split("\\s+")).mapToInt(Integer::parseInt).toArray();
}
DEMO:
1. Output
[2, 3, 6]
2. Code
import java.util.*;
public class HelloWorld {
public static void main(String args[]) {
String s = "2x+3y=6";
int[] array = decompose(s);
System.out.println(Arrays.toString(array));
}
public static int[] decompose(String s) {
return Arrays.stream(s.replaceAll("[^0-9]", " ").split("\\s+")).mapToInt(Integer::parseInt).toArray();
}
}

want to delete star and the char in front and follow it, why my code does not work

Return a version of the given string, where for every star (*) in the string the star and the chars immediately to its left and right are gone. So "ab*cd" yields "ad" and "ab**cd" also yields "ad". It is a coding bat problem.
public class DeleteStar {
public static void main(String[] args) {
String s=deleteS("ab*ab");
System.out.println(s);
}
public static String deleteS(String s)
{
StringBuilder sb=new StringBuilder();
for (int i=0;i<s.length();i++)
{
sb.append(s.charAt(i));
}
System.out.println(sb.toString());
for (int i=0;i<sb.length();i++)
{
if (sb.charAt(i)+""=="*")
{
sb.deleteCharAt(i);
sb.deleteCharAt(i-1);
sb.deleteCharAt(i+1);
}
}
return sb.toString();
}
}
When you delete a character, you also shorten the length of the string by 1. So if you call your sequence on "ab*cd", suppose we know i = 2, we'll get:
sb.deleteCharAt(i); // We now have "abcd"
sb.deleteCharAt(i-1); // We now have "acd"
sb.deleteCharAt(i+1); // Oops! "acd" has no index of 3!
But even if we've done the above correctly, if we have two adjacent stars, this will create problems. So we should check whether the adjacent characters are stars or not before we delete. For instance, if we run this on "ab**cd", we'll get:
// This is the correct way if no stars are adjacent to each other.
// But if there are? Testing on "ab**cd"
sb.deleteCharAt(i-1); // We now have "a**cd"
sb.deleteCharAt(i-1); // We now have "a*cd"
sb.deleteCharAt(i-1); // We now have "acd"...wait, we need to delete c too!
Another problem is that you are modifying the string builder when you are iterating through it. This is a bad idea, because you will have the wrong indices! Considering the following:
// We execute this on "ab*cd*ef", expecting "af".
for (int i = 0; i < sb.length(); i++) { // length = 8
if (sb.charAt(i) + "" == "*") {
// First execution, i = 2. Second, i = 5.
sb.deleteCharAt(i-1);
sb.deleteCharAt(i-1);
sb.deleteCharAt(i-1);
// After we executed the first time, we get that sb's length
// is now 5! Wait, so next time when we try to delete the i-1
// character, we are removing...f? That cannot be right!
}
}
Since this is a coding exercise, I've left the actual debugging to yourself. It is a learning process to figure out why things are the way they are! :)
Well you have to use the equals method for comparing objects
== checks if it is the same instance not if it has the same value
ie:
(sb.charAt(i)+""=="*")
shoudl be
((sb.charAt(i)+"").equals("*"))
Also you should use the replace method of string
ie:
"abxxxcd".replace("xxx","");
I think * may be interpreted as a regular expression so you have to escape it using \ (Im not sure you have to try it or read the javadoc)
Another think which could fix it is this:
(sb.charAt(i)=='*')
'*' is interpreted as a character
What about a solution like that?
package eu.duernau.stackoverflow;
public class Sov33355763 {
public static void main(String[] a) {
String s = deleteS("aba*b");
System.out.println(s);
s = deleteS("ab*ab");
System.out.println(s);
s = deleteS("ab*cd*ef*ghij*");
System.out.println(s);
s = deleteS("0*ab*cd*ef*ghij*");
System.out.println(s);
s = deleteS("****acd****");
System.out.println(s);
}
private static String deleteS(String s) {
StringBuilder sb = new StringBuilder(s);
int lastStarPosition;
do {
lastStarPosition = sb.lastIndexOf("*");
if (lastStarPosition > 1 && lastStarPosition + 1 < sb.length()) {
sb.replace(lastStarPosition - 1, lastStarPosition + 2, "");
} else {
if (lastStarPosition + 1 == sb.length()) {
sb.replace(lastStarPosition - 1, lastStarPosition + 1, "");
} else {
if (lastStarPosition > 0) {
sb.replace(lastStarPosition - 1, lastStarPosition + 2, "");
} else {
if (lastStarPosition > -1) {
sb.replace(lastStarPosition, lastStarPosition + 2, "");
}
}
}
}
} while (lastStarPosition > -1);
return sb.toString();
}
}
produces
ab
ab
ahi
hi
d
I only see this happening with Regular Expressions:
Code:
String pattern1 = ".?[*]+.?";
s = s.replaceAll(pattern1, "");

Categories