Finding Letter Combinations - java

For a string such as -u--('-' indicates a blank space), i'm given a letter lets say "d". The goal is for me to find all the combinations in which the letter d can be substituted in for the "-". A little hard to explain but, this is what an intended output would look like:
du--
dud-
du-d
dudd
-ud-
-udd
-u-d
I can't seem to find a set way of finding the combinations because I need to be able to find combinations of various lengths such as:
-u-----, or ----u-
Thanks for any future help, if more clarification is needed I can try to explain a little better.

This is best done recursively.
Base case: combinations of the empty string are [].
Recursive case 1: to get combinations of u....., get all combinations of .....; then prefix each one with "u".
Recursive case 2: to get combinations of -....., get all combinations of .....; then prefix each one with "d", and prefix each one with -, and concatenate the two arrays.

This is my solution to your problem:
public String[] getCombinations( String inputString ) {
int dashCount = 0;
for( int i = 0; i < inputString.length(); i++ ) { // checks how many '-' you have in the String
if( inputString.charAt(i) == '-' ) dashCount++;
}
int uPosition = inputString.indexOf('u');
ArrayList<String> arr = new ArrayList<String>();
for( int i = 1; i <= Math.pow(2,dashCount)-1; i++ ) {
String temp = String.format("%"+dashCount+"s", Integer.toBinaryString(i)).replace(' ', '0'); // this returns a dashCount-bit binary number like 0001, 0010, for a dashCount of 4
temp = temp.replace( '0', '-' );
temp = temp.replace( '1', 'd' );
arr.add( temp.substring(0,uPosition) + "u" + temp.substring(uPosition, temp.length()) );
}
Object[] tempArr = arr.toArray();
return Arrays.copyOf(tempArr, tempArr.length, String[].class);
}
Idea is, treat all '-' as bits in a binary number, so count all occurrences of '-'. For convenience, we say we have n bits in the binary number.
Numbers from 1 to (2^n)-1 in binary will yield all possible combinations of 1's and 0's for the string.
Swap all '0' with '-', and swap all '1' with 'd'.
Insert 'u' to its original position.
Boom.
EDIT: altered code so you don't need third-party libraries.

Related

"number of segments in a string" not working for a particular input

I have to find "contiguous sequence of non-space characters" in a string.
My output is coming wrong for the input
Input=", , , , a, eaefa"
My answer is coming as 13 instead of 6.Though I have only counted words except for spaces.
class Solution {
public int countSegments(String s)
{
if(s.isEmpty()){
return 0;
}
else
{
int count=0;
String s1[]=s.split(" ");
for(int i=0;i<s1.length;i++)
{
if(s1[i]!=" ")
count++;
}
return count;
}
}
}
Others have suggesting using:
s.split("\\s+").length
However, there are complications in using split. Specifically, the above will give incorrect answers for strings with leading spaces. Even if these issues are fixed it's still overly expensive as we're creating count new strings, and an array to hold them.
We can implement countSegments directly by iterating through the string and counting the number of times we go from a non-space character to a space character, or the end of the string:
public static int countSegments(String s)
{
int count = 0;
for(int i=1; i<=s.length(); i++)
{
if((s.charAt(i-1) != ' ') && (i == s.length() || s.charAt(i) == ' ')) count++;
}
return count;
}
Test:
for(String s : new String[] {"", " ", "a", " a", "a ", " a ", ", , , , a, eaefa"})
System.out.format("<%s> : %d%n", s, countSegments(s));
Output:
<> : 0
< > : 0
<a> : 1
< a> : 1
<a > : 1
< a > : 1
<, , , , a, eaefa> : 6
You should use split on multiple spaces, and then you have the segments already divided up for you, so you don't need to make a for-loop or anything.
//The trim is because split gets messed up with leading spaces, as SirRaffleBuffle said
s = s.trim();
if (s.isEmpty()) return 0;
return s.split("\\s+").length;
If you want only sequences of alphanumeric characters, you can try this regex instead: "\\W+"
If you want only sequences of English letters, you can do the same thing but with the regex "[^A-Za-z]+".
Here, it splits on multiple spaces instead of just one.
The way you're currently doing it, you count every single letter that's not a whitespace instead of "contiguous sequences of no-space characters". That's why you're getting 13 instead of 6.
Notice that count is incremented anytime it finds something that isn't a space, but if you do want to do this with a for-loop, you should have a boolean flag telling you that you've entered a sequence, so you only increment count when that flat was previously false (you were outside a sequence) and then you find a space.
Also, using != for String comparison is wrong, you should use the equals method.
“number of segments in a string” not working for a particular input
You can do it easily by using the regex, \\s+ as follows:
public class Main {
public static void main(String[] args) {
String str = ", , , , a, eaefa";
str = str.trim();// Remove the leading and trailing space
System.out.println(str.isEmpty() ? 0 : str.split("\\s+").length);
}
}
Output:
6
The regex, \\s+ matches on one or more consecutive spaces.
On a side note, you are using != to compare strings, which is not correct. Note that == and != are used to compare the references, not the values.

Find out recursive pattern in a string java

In one of my interview I had asked one program on java string, I am unable to answer it. I don't know it is a simple program or complex one. I have explored on the internet for it, but unable to find the exact solution for it. My question is as follow,
I have supposed one string which contains recursive pattern like,
String str1 = "abcabcabc";
In above string recursive pattern is "abc" which repeated in one string, because this string only contains "abc" pattern recursively.
if I passed this string to a function/method as a parameter that function/method should return me "This string has a recursive pattern." If that string doesn't have any recursive pattern then simply function/method should return "This string doesn't contain the recursive pattern."
Following are probabilities,
String str1 = "abcabcabc";
//This string contains recursive pattern 'abc'
String str2 = "abcabcabcabdac";
//This string doesn't contains recursive pattern
String str2 = "abcddabcddabcddddabc";
//This string contains recursive pattern 'abc' & 'dd'
Can anybody suggest me solution/algorithm for this, I am struggling with it. What is the best way for different probabilities, so that I implement?
From LeetCode
public boolean repeatedSubstringPattern(String str) {
int l = str.length();
for(int i=l/2;i>=1;i--) {
if(l%i==0) {
int m = l/i;
String subS = str.substring(0,i);
StringBuilder sb = new StringBuilder();
for(int j=0;j<m;j++) {
sb.append(subS);
}
if(sb.toString().equals(str)) return true;
}
}
return false;
}
The length of the repeating substring must be a divisor of the length of the input string
Search for all possible divisor of str.length, starting for length/2
If i is a divisor of length, repeat the substring from 0 to i the number of times i is contained in s.length
If the repeated substring is equals to the input str return true
Solution is not in Javascript. However, problem looked interesting, so attempted to solve it in python. Apologies!
In python, I wrote a logic which worked [Could be written much better, thought the logic would help you]
Script is
def check(lst):
return all(x in lst[-1] for x in lst)
s = raw_input("Enter string:: ")
if check(sorted(s.split(s[0])[1:])):
print("String, {} is recursive".format(s))
else:
print("String, {} is NOT recursive".format(s))
Output of the script:
[mac] kgowda#blr-mp6xx:~/Desktop/my_work/play$ python dup.py
Enter string:: abcabcabcabdac
String, abcabcabcabdac is NOT recursive
[mac] kgowda#blr-mp6xx:~/Desktop/my_work/play$ python dup.py
Enter string:: abcabcabc
String, abcabcabc is recursive
[mac] kgowda#blr-mp6xx:~/Desktop/my_work/play$ python dup.py
Enter string:: abcddabcddabcddddabc
String, abcddabcddabcddddabc is recursive
This can also be solved using a part of the Knuth–Morris–Pratt Algorithm.
The idea is to build a 1-D array with each entry representing a character in the word. For each character i in the word we check if there is a prefix which is also a suffix in the word up 0 to i. The reason being if we have common suffix and prefix we can continue searching from the character after prefix ends which we update the array with the corresponding character index.
For s="abcababcababcab", the array will be
Index : 0 1 2 3 4 5 6 7 8
String: a b c a b c a b c
KMP : 0 0 0 1 2 3 4 5 6
For Index = 2, we see that there is no suffix which is also the prefix in the string ab i.e) up until Index = 2
For Index = 4, the suffix ab(Index = 3, 4) is same as the prefix ab(Index = 0, 1) so we update the KMP[4] = 2 which is the index of the pattern from which we have to resume searching.
Thus KMP[i] holds the index of the string s where prefix matches the longest possible suffix in the range 0 to i plus 1. Which essentially means that the a prefix with length index + 1 - KMP[index] exists in the string previously. using this information we can find out if all the substrings of that length are the same.
For Index = 8, we know KMP[index] = 6, which means there is a prefix(s[3] to s[5]) of length 9 - 6 = 3 which is equal to the suffix(s[6] to s[8]), If this is the only repetitive pattern we have this will follow
For a clearer explanation of this algorithm please check this video lecture.
This table can be build in linear time,
vector<int> buildKMPtable(string word)
{
vector<int> kmp(word.size());
int j=0;
for(int i=1; i < word.size(); ++i)
{
j = word[j] == word[i] ? j : kmp[j-1];
if(word[j] == word[i])
{
kmp[i] = j + 1;
++j;
}
else
{
kmp[i] = j;
}
}
return kmp;
}
bool repeatedSubstringPattern(string s) {
auto kmp = buildKMPtable(s);
if(kmp[s.size() -1] == 0) // Occurs when the string has no prefix with suffix ending at the last character of the string
{
return false;
}
int diff = s.size() - kmp[s.size() -1]; //Length of the repetitive pattern
if(s.size() % diff != 0) //Length of repetitive pattern must be a multiple of the size of the string
{
return false;
}
// Check if that repetitive pattern is the only repetitive pattern.
string word = s.substr(0, diff);
int w_size = word.size();
for(int i=0; i < w_size; ++i)
{
int j = i;
while(j < s.size())
{
if(word[i] == s[j])
{
j += w_size;
}
else
{
return false;
}
}
}
return true;
}
If you know the 'parts' in advance, then the answer could be Recursive regular expressions, it seems.
So for abcabcabc we need an expression like abc(?R)* where:
abc matches the literal characters
(?R) recurses the pattern
A * to match between zero and unlimited number of times
The third one is a little trickier. See this regex101 link but it looks like:
((abc)|(dd))(?R)*
where we have either 'abc' or 'dd' and there are any number of these.
Otherwise, I don't see how you could determine from just a string that it has some undefined recursive structure like this.

modify empty characters in a character array

I'm attempting to take in a string from the console of a certain length and set the empty characters in the string to an asterisk.
System.out.println("Enter a string of digits.");
someString = input.next();
if(someString.matches("\\d{0,9}")) {
charArr = someString.toCharArray();
for ( char digit: charArr) {
if(!Character.isDefined(charArr[digit])){
charArr[digit] = '*';
}
}
System.out.printf("Your string is: %s%n", new String(charArr));
This code is throwing an array index out of bounds exception and I'm not sure why.
for ( char digit: charArr) will iterate over each character from charArr.
Thus, digit contains a character value from charArr.
When you access the element from charArr by writing charArr[digit], you are converting digit from datatype char to int value.
For example, you have charArr = new char[]{'a','b','c'}.
charArr['a'] is equivalent to charArr[97] but charArr has size of length 3 only.
Thus, charArr cannot access the element outsize of its size and throws ArrayIndexOutOfBoundsException.
Solution: loop through the array index wise rather than element wise.
for(int i = 0; i < charArr.length; i++) {
// access using charArr[i] instead of charArr[digit]
...
}
Think you could do it in one line with:
newString = someString.replaceAll("\\s", "*");
"\s" is the regex pattern for a whitespace character.
I think you're mixing your for blocks. In your example, you're going over every character in your someString.toCharArray() so you can't do !Character.isDefined(charArr[digit]) because digit is a char, not an int. You can't take the index of an array with a char.
If you're checking purely if a character is a space, you can simply do one of the following:
if (digit != ' ')
if (!Character.isWhiteSpace(digit)
if (Character.isDigit(digit))
This loop statement:
for (char digit: charArr) {
iterates the values in the array. The values have type char and can be anything from 0 to 65535. However, this statement
if (!Character.isDefined(charArr[digit])) {
uses digit as an index for the array. For that to "work" (i.e. not throw an exception), the value needs to be in the range 0 to charArr.length - 1. Clearly, for the input string you are using, some of those values are not acceptable as indexes (e.g. value >= charArr.length) and an exception ensues.
But you don't want to fix that by testing value is in the range required. The values of value are not (from a semantic perspective) array indexes anyway. (If you use them as if they are indexes, you will end up missing some positions in the array.)
If you want to index the values in the array, do this:
for (int i = 0; i < charArr.length; i++) {
and then use i as the index.
Even when you have fixed that, there is still a problem with your code ... for some usecases.
If your input is encoded using UTF-8 (for example) it could include Unicode codepoints (characters) that are greater than 65535, and are encoded in the Java string as two consective char values. (A so-called surrogate pair.) If your string contains surrogate pairs, then isDefined(char) is not a valid test. Instead you should be using isDefined(int) and (more importantly) iterating the Unicode codepoints in the string, not the char values.

How to check how many letters are in a string in java?

How do you check how many letters are in a Java string?
How do you check what letter is in a certain position in the string (i.e, the second letter of the string)?
A)
String str = "a string";
int length = str.length( ); // length == 8
http://download.oracle.com/javase/7/docs/api/java/lang/String.html#length%28%29
edit
If you want to count the number of a specific type of characters in a String, then a simple method is to iterate through the String checking each index against your test case.
int charCount = 0;
char temp;
for( int i = 0; i < str.length( ); i++ )
{
temp = str.charAt( i );
if( temp.TestCase )
charCount++;
}
where TestCase can be isLetter( ), isDigit( ), etc.
Or if you just want to count everything but spaces, then do a check in the if like temp != ' '
B)
String str = "a string";
char atPos0 = str.charAt( 0 ); // atPos0 == 'a'
http://download.oracle.com/javase/7/docs/api/java/lang/String.html#charAt%28int%29
If you are counting letters, the above solution will fail for some unicode symbols. For example for these 5 characters sample.length() will return 6 instead of 5:
String sample = "\u760c\u0444\u03b3\u03b5\ud800\udf45"; // 瘌фγε𐍅
The codePointCount function was introduced in Java 1.5 and I understand gives better results for glyphs etc
sample.codePointCount(0, sample.length()) // returns 5
http://globalizer.wordpress.com/2007/01/16/utf-8-and-string-length-limitations/
To answer your questions in a easy way:
a) String.length();
b) String.charAt(/* String index */);
1) To answer your question:
String s="Java";
System.out.println(s.length());
I could not get any of these answers to work for me using UTF-8. If you are using UTF-8, have a look at this post. I ended up using Guava's Utf8.

Get int from String, also containing letters, in Java

How can I get the int value from a string such as 423e - i.e. a string that contains a number but also maybe a letter?
Integer.parseInt() fails since the string must be entirely a number.
Replace all non-digit with blank: the remaining string contains only digits.
Integer.parseInt(s.replaceAll("[\\D]", ""))
This will also remove non-digits inbetween digits, so "x1x1x" becomes 11.
If you need to confirm that the string consists of a sequence of digits (at least one) possibly followed a letter, then use this:
s.matches("[\\d]+[A-Za-z]?")
The NumberFormat class will only parse the string until it reaches a non-parseable character:
((Number)NumberFormat.getInstance().parse("123e")).intValue()
will hence return 123.
Unless you're talking about base 16 numbers (for which there's a method to parse as Hex), you need to explicitly separate out the part that you are interested in, and then convert it. After all, what would be the semantics of something like 23e44e11d in base 10?
Regular expressions could do the trick if you know for sure that you only have one number. Java has a built in regular expression parser.
If, on the other hands, your goal is to concatenate all the digits and dump the alphas, then that is fairly straightforward to do by iterating character by character to build a string with StringBuilder, and then parsing that one.
You can also use Scanner :
Scanner s = new Scanner(MyString);
s.nextInt();
Just go through the string, building up an int as usual, but ignore non-number characters:
int res = 0;
for (int i=0; i < str.length(); i++) {
char c = s.charAt(i);
if (c < '0' || c > '9') continue;
res = res * 10 + (c - '0');
}
Perhaps get the size of the string and loop through each character and call isDigit() on each character. If it is a digit, then add it to a string that only collects the numbers before calling Integer.parseInt().
Something like:
String something = "423e";
int length = something.length();
String result = "";
for (int i = 0; i < length; i++) {
Character character = something.charAt(i);
if (Character.isDigit(character)) {
result += character;
}
}
System.out.println("result is: " + result);

Categories

Resources