I have an Array of Characters ' A ' and ' B '
Whats a smart way to count the ' Runs '
example :
AABBBAAAABBAB
should be 6 because there are 6 runs as seen below.
1 2 3 4 5 6
AA BBB AAAA BB A B
tried something like:
if (!(sortedRuns.get(i) == sortedRuns.get(i+1))) {
runsAmount++;
}
but obviously run into 'out of bound problems'
Issue
e.g char array A A B B C C
array positions 0 1 2 3 4 5
when you reach at the position 5 then sortedRuns.get(i+1) mean 5+1=6 which doesn't exist hence the exception
Solution
1.) Traverse the array
2.) Increment run if char changes and assign new char to temp char
String s="AABBBAAAABBAB";
int run=1;
// fetch first char
char temp=s.charAt(0);
// traverse char array
for (char ch : s.toCharArray()) {
// assign value of new char to temp and increment run
// when value of char changes
if (ch!=temp) {
run++;
temp=ch;
}
}
System.out.println(run);
Output:
6
I would use an auxiliar variable to save the last character. Then increment when a new character is different from my auxiliar variable, then update this variable. Easy and not out of bounds exceptions.
u can try this easy one-liner:
public static void main(String[] args) {
String s="AABBBAAAABBAB";
int charCount = s.length() - s.replaceAll("A", "").length();
System.out.println(charCount);
System.out.println(s);
}
You could use a regular expression.
/(.)\1*/ gives 6 matches.
(.) matches any character.
\1* then matches as many of the first character as possible.
Java Example:
final String regex = "(.)\\1*";
final String string = "AABBBAAAABBAB";
final Pattern pattern = Pattern.compile(regex);
final Matcher matcher = pattern.matcher(string);
int count = 0;
while (matcher.find()) {
count ++;
System.out.println("Full match: " + matcher.group(0));
for (int i = 1; i <= matcher.groupCount(); i++) {
System.out.println("Group " + i + ": " + matcher.group(i));
}
}
System.out.println("Match count: " + count);
This has the advantage of working with any character string.
Related
I have created a program that allows the user to enter 5 words. These words
are stored into a string array. When the user is finished, the number of times a word beginning with the letter ‘B’ was entered, lower or uppercase is displayed. Now I also have to re-state the B words.
So this is the code I have so far that finds how many of the words entered starts with "b"
int fromIndex = 0;
int count = 0;
String words[] = new String [5];
for (int x = 0 ; x <= words.length - 1 ; x = x + 1)
{
System.out.print ("Please enter a word: ");
words [x] = kbi.readLine ();
fromIndex = 0;
words [x] = words [x].toLowerCase ();
fromIndex = words [x].indexOf ("b", fromIndex);
if (fromIndex == 0) // STARTS WITH B
{
count++;
}
}
System.out.println ("You entered " + count + " 'B' words and they were: ");
I was thinking that I could use an if statement to print the b words. Like:
if (words.charAt(0) == "b")
{
System.out.println (words);
}
but that doesn't really seem to work and I didn't really think it would, I'm kind of at a loss of what to do.
I hope I can receive some help on this, thank you in advance.
in your code words is not an String(it is an array of String) so it doesn't have charAt method that you used above. you have 5 String in your words array so if you want to write all String in your array which start with character 'b' you should loop through your array and print all that start with 'b', like this:
for(String str : words){
if (str.charAt(0) == 'b'){
System.out.println(str);
}
some tips:
in java 7 String has startsWith method that you can use. if you are using java 6 check if it has it too:
for(String str : words){
if (str.startsWith("b", 0)){
System.out.println(str);
}
It's because charAt returns char instead of String, so you would have to change your comparison:
if (words.charAt(0) == 'b')
Other possibility would be to use regex "b.*" or even easier - String comes with startsWith method, so you can simply do this:
if (words.startsWith("b"))
I want to split a string into parts of 3 words in Java.
For example:
I want to walk in the park with my father
I want to have a string: "I want to", and another string:"walk in the", etc.
How would I do this?
Here is a solution using RegEx
String sentence = "I want to walk in the park with my father";
Pattern pattern = Pattern.compile("\\w+ \\w+ \\w+ ");
Matcher matcher = pattern.matcher(sentence);
while (matcher.find()) {
System.out.println(matcher.group());
}
Notice that whit this expression the last word 'father' is not matched.
For the non-RegEx solution, I would use something like this
String sentence = "I want to walk in the park with my father";
String[] words = sentence.split(" ");
List<String> threeWords = new ArrayList<>();
int length = words.length;
for (int ind = 2; ind < length; ind += 3) {
threeWords.add(words[ind - 2] + " " + words[ind - 1] + " " + words[ind]);
}
if (length % 3 == 1) {
threeWords.add(words[length - 1]);
} else if (length % 3 == 2) {
threeWords.add(words[length - 2] + " " + words[length - 1]);
}
For me creating a temporary ArrayList (aka words), and removing 3 words at a time, concatenating them into a String, and adding it to my final ArrayList worked just fine, although this probably isn't extremely performance efficient, it gets the job done & it's simple to understand.
// finalWords is your result
ArrayList<String> finalWords = new ArrayList<String>();
ArrayList<String> words = new ArrayList<String>();
for(String str : "I want to walk in the park with my father".split(" "))
words.add(str);
while(words.size() > 0)
{
String str = "";
for(int i = 0; i < 3; i++)
{
if(words.size() > 0)
{
str += words.get(0) + " ";
words.remove(0);
}
}
finalWords.add(str);
}
EDIT: Since you wrote this:
I know how to split it in individual words, but not into groups.
in the comments, splitting it into groups of words is simple. First, you split your sentence into words, then you concatenate those words into new strings, 3 at a time, and add the concatenated strings to a list/array of your choice.
I have this working code to print string permutations without repetitions, but not able to wrap my head around how is it working as in logic. Any suggestions will be really helpful.
private static void permutation(String input, String sofar) {
if (input.equals("")) {
System.out.println(count + " " + sofar);
count++;
}
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (input.indexOf(c, i + 1) != -1)
continue;
permutation(input.substring(0, i) + input.substring(i + 1), sofar+c);
}
}
Function call:
String input = "ABBCD";
permutation(input, "");
for (int i = 0; i < input.length(); i++) {
The above for loop is doing the magic
Input ABCD
Iterations
input: BCD sofar: A .... recursion goes on
input: ACD sofar: B ....
input: ABD sofar: C ....
input: ABC sofar: D .....
Hope this helps
Just remember that recursion is usually a stop condition, and an attempt to solve a smaller problem using the recursive call, under the assumption that the recursion works.
I've commented the code so you can replace that with your copy to keep track of what it's doing when you get back to it. Add your own comments once you understand as they'll help you follow what happens:
Part 1: The basic condition / stop condition:
if (input.equals("")) {
System.out.println(count + " " + sofar);
count++;
}
This part stops the recursion and returns a result, the base case being an empty string, which has a single permutation that is also an empty string.
Part 2: Iterating smaller problems.
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
// ...
permutation(input.substring(0, i) + input.substring(i + 1), sofar+c);
}
This part uses the recursive call on a smaller (by one character) string, to solve the problem. It calls the same string omitting a character it prepends to whatever following results it generates. We know the call generates all permutations (that's our assumption). So we now know what the recursion does.
Part 2.1: The de-duplicating "if":
This is probably the trickiest part here...
if (input.indexOf(c, i + 1) != -1)
continue;
Let's figure this out. What it means, is: "try and find a character the same as the one selected, and if one exists, skip this iteration and it's generated solutions".
Think of a word like "ABBA" it will skip the first "A" and "B", but not the last ones. Why? Well, since order of similar characters does not matter (if we tag the character A1 B1 B2 A2, and now replace them: A2 B2 B1 A1, this is still the same word, so there is only one permutation for words like "AA", since A1 A2 is the same as A2 A1.
Taking the last characters is easier, since we don't need to maintain a list of the characters we already used in this iteration.
The full code with basic comments:
private static void permutation(String input, String sofar) {
if (input.equals("")) {
// this is the stop condition
// the only permutation of "" is ""
System.out.println(count + " " + sofar);
// this counts how many permutations were outputted.
count++;
}
for (int i = 0; i < input.length(); i++) {
// this loop basically means "take every
// possible character, and append permutations of all
// other characters to it.
char c = input.charAt(i);
if (input.indexOf(c, i + 1) != -1)
// this makes sure we only take a single "A" or "B"
// character in words like "ABBA", since selecting
// the same character would create duplicates
continue;
// this creates a new string without the selected character
// and under the assumption the recursion works
// appends all permutations of all other characters
// to it
permutation(input.substring(0, i) + input.substring(i + 1), sofar+c);
}
}
if (input.equals("")) {
System.out.println(count + " " + sofar);
count++;
}
This step is passed as the input is not "". Note that you could simply use input.empty() here. The only thing to remember here is that count have not been incremented.
for (int i = 0; i < input.length(); i++) {
This will, loop over all character of the input
char c = input.charAt(i);
if (input.indexOf(c, i + 1) != -1)
This check if the next character is equal to the current one, if it does then it will jump directly to the next iteration(the next character) using the continue keyword.
If it does not, then it will recall the method (We call that recursivity), passing in the string without the current char. But giving it back to sofar.
permutation(input.substring(0, i) + input.substring(i + 1), sofar+c);
Now in the case where input is empty,
The count of non-distinct character will be printed + all these character.
This question already has answers here:
Java regex - overlapping matches
(3 answers)
Closed 8 years ago.
I am trying to understand pattern matching in Java. However, I am stumped by the output of the code below. It prints a count of 2 while matching "aa" against "aaaa" however I expect it to print 3 because 'a' followed by 'a' happens thrice in the given string. Can anybody explain what's the issue here?
Pattern p = Pattern.compile("aa");
Matcher m = p.matcher("aaaa");
int count = 0;
while(m.find())
count++;
System.out.println(count);
The matcher will not find overlapping matches. So since the first match is found at index 0 with a length of two, it won't start looking for the next match until index 2, and the potential match starting at index 1 isn't found.
If you wanted to find overlapping matches you could use m.find(start) where start is an index one higher than your previous match. For example:
Pattern p = Pattern.compile("aa");
Matcher m = p.matcher("aaaa");
int count = 0;
int start = 0;
while(m.find(start)) {
count++;
start = m.start() + 1;
}
System.out.println(count);
When searching for literal strings, you can also use indexOf:
public class Test {
public static final void main(String[] ignored) {
String toFind = "aa";
String toSearch = "aaaa";
int idxLastFound = 0;
int foundCount = 0;
while(idxLastFound <= (toSearch.length() - toFind.length())) {
idxLastFound = toSearch.indexOf(toFind, idxLastFound);
if(idxLastFound == -1) {
break;
}
System.out.println("Found at " + idxLastFound);
idxLastFound++;
foundCount++;
}
System.out.println("Found " + foundCount + " times");
}
}
Output:
[C:\java_code\]java Test
Found at 0
Found at 1
Found at 2
Found 3 times
I have a string, for ex:
There exists a word *random*.
random will be a random word.
How can I use a regular expression to replace every character of random with * and have this result:
There exists a word ********.
So the * replaces every character, in this case 6 characters.
Notice that I am after to replace only the word random, not the surroundings *.
So far I have:
str.replaceAll("(\\*)[^.]*(\\*)", "\\*");
But it replaces *random* with *, instead of the desired ******** (total of 8).
Any help, really appreciated...
If you have just a single word like that: -
As far as current example is concerned, if you are having just a single word like that, then you can save yourself from regex, by using some String class methods: -
String str = "There exists a word *random*.";
int index1 = str.indexOf("*");
int index2 = str.indexOf("*", index1 + 1);
int length = index2 - index1 - 1; // Get length of `random`
StringBuilder builder = new StringBuilder();
// Append part till start of "random"
builder.append(str.substring(0, index1 + 1));
// Append * of length "random".length()
for (int i = 0; i < length; i++) {
builder.append("*");
}
// Append part after "random"
builder.append(str.substring(index2));
str = builder.toString();
If you can have multiple words like that: -
For that, here's a regex solution (This is where it starts getting a little complex): -
String str = "There exists a word *random*.";
str = str.replaceAll("(?<! ).(?!([^*]*[*][^*]*[*])*[^*]*$)", "*");
System.out.println(str);
The above pattern replaces all the characters that is not followed by string containing even numbers of * till the end, with a *.
Whichever is appropriate for you, you can use.
I'll add an explanation of the above regex: -
(?<! ) // Not preceded by a space - To avoid replacing first `*`
. // Match any character
(?! // Not Followed by (Following pattern matches any string containing even number of stars. Hence negative look-ahead
[^*]* // 0 or more Non-Star character
[*] // A single `star`
[^*]* // 0 or more Non-star character
[*] // A single `star`
)* // 0 or more repetition of the previous pattern.
[^*]*$ // 0 or more non-star character till the end.
Now the above pattern will match only those words, which are inside a pair of stars. Provided you don't have any unbalanced stars.
You can extract the word between * and do a replaceAll characters with * on it.
import java.util.regex.*;
String txt = "There exists a word *random*.";
// extract the word
Matcher m = Pattern.compile("[*](.*?)[*]").matcher(txt);
if (m.find()) {
// group(0): *random*
// group(1): random
System.out.println("->> " + m.group(0));
txt = txt.replace(m.group(0), m.group(1).replaceAll(".", "*"));
}
System.out.println("-> " + txt);
You can see it on ideone: http://ideone.com/VZ7uMT
try
String s = "There exists a word *random*.";
s = s.replaceAll("\\*.+\\*", s.replaceAll(".*(\\*.+\\*).*", "$1").replaceAll(".", "*"));
System.out.println(s);
output
There exists a word ********.
public static void main(String[] args) {
String str = "There exists a word *random*.";
Pattern p = Pattern.compile("(\\*)[^.]*(\\*)");
java.util.regex.Matcher m = p.matcher(str);
String s = "";
if (m.find())
s = m.group();
int index = str.indexOf(s);
String copy = str;
str = str.substring(0, index);
for (int i = index; i < index + s.length(); i++) {
str = str + "*";
}
str = str + copy.substring(index + s.length(), copy.length());
System.out.println(str);
}