Greatest number of consecutive vowels - java

I'm trying to write a function that takes in a String and returns the greatest number of consecutive equivalent vowels in the String.
Here's my attempt:
public static final String VOWELS = "aeiou";
public static int consecutiveVowelsInLine(String line) {
int longestVowels = 0;
int candidateLength = 0;
for (int i = 0; i < line.length() - 1; i++) {
if (isVowel(line.charAt(i))) {
if (line.charAt(i) == line.charAt(i+1)) {
candidateLength++;
}
} else {
candidateLength = 0;
}
longestVowels = Math.max(longestVowels, candidateLength);
}
return longestVowels;
}
public static boolean isVowel(char c) {
VOWELS.contains(c.toLowerCase());
}
The problem is this doesn't handle the case where the String is a single character that's a vowel. So if the String is just "a", my code gives back 0 instead of 1.
As said before, the vowels have to be the same.
Testcases:
a -> 1
b -> 0
ae -> 1
aeae -> 1
aab -> 2
aba -> 1
abee -> 2

I think you aim to do too much in the loop: instead of looking to the character next, concentrate on the current character and maintain a state that stores the previous vowel:
public static int consecutiveVowelsInLine(String line) {
int longestVowels = 0;
int candidateLength = 0;
char vowel = 'b'; //b is not a vowel
for (int i = 0; i < line.length(); i++) {
char ci = line.charAt(i);
if (isVowel(ci)) {
if (ci == vowel) { //the same as the other one
candidateLength++;
} else {
candidateLength = 1;
}
vowel = ci;
} else {
candidateLength = 0;
vowel = 'b';
}
longestVowels = Math.max(longestVowels, candidateLength);
}
return longestVowels;
}
Here vowel stores the current vowel sequences you are working with. In the beginning we use b, simple because that is not a vowe. In case we encounter a vowel, that vowel is stores in vowel and we update the candidateLength accordingly. In case we encounter a non-vowel, we set vowel back to b (or another non-vowel).
Demo:
There were some problems with your isVowel method as well, a running implementation with a few testcases can be found here.

Here's one problem:
if (line.charAt(i) == line.charAt(i+1)) {
candidateLength++;
}
If the string is only one character, you're checking the character against null. Add a check, something like this:
if (line.length() == 1 && isVowel(line.charAt(0)) {
etc.
}

Simply change it like:
public static int consecutiveVowelsInLine( String line ){
int result = findConsecutiveMaxValue( line );
if( result == 0 ){
result = findSingleVowel( line );
}
return result;
}
private static int findSingleVowel( String line ){
for( int i = 0; i < line.length(); i++ ){
if( isVowel( line.charAt( i ) ) ){ return 1; }
}
return 0;
}
private static int findConsecutiveMaxValue( String line ){
int longestVowels = 0;
int candidateLength = 0;
for( int i = 0; i < line.length() - 1; i++ ){
if( isVowel( line.charAt( i ) ) ){
if( line.charAt( i ) == line.charAt( i + 1 ) ){
candidateLength++;
}
}
else{
candidateLength = 0;
}
longestVowels = Math.max( longestVowels, candidateLength );
}
return longestVowels;
}

Change:
if (line.charAt(i) == line.charAt(i+1)) {
candidateLength++;
}
to:
if (candidateLength == 0 || line.charAt(i) == line.charAt(i-1)) {
candidateLength++;
}
Additionally the condition in for() loop looks suspicious - use getLength() instead of getLength()-1.

Related

Java: Find the longest substring without any number and at least one upper case character

Came across a programming exercise and was stuck. The problem is:
You need to define a valid password for an email but the only
restrictions are:
The password must contain one uppercase character
The password should not have numeric digit
Now, given a String, find the length of the longest substring which
is a valid password. For e.g Input Str = "a0Ba" , the output should
be 2 as "Ba" is the valid substring.
I used the concept of longest substring without repeating characters which I already did before but was unable to modify it to find the solution to above problem. My code for longest substring without repeating characters is:
public int lengthOfLongestSubstring(String s) {
int n = s.length();
Set<Character> set = new HashSet<>();
int ans = 0, i = 0, j = 0;
while (i < n && j < n) {
// try to extend the range [i, j]
if (!set.contains(s.charAt(j))){
set.add(s.charAt(j++));
ans = Math.max(ans, j - i);
}
else {
set.remove(s.charAt(i++));
}
}
return ans;
}
How about
final String input = "a0Ba";
final int answer = Arrays.stream(input.split("[0-9]+"))
.filter(s -> s.matches("(.+)?[A-Z](.+)?"))
.sorted((s1, s2) -> s2.length() - s1.length())
.findFirst()
.orElse("")
.length();
out.println(answer);
Arrays.stream(input.split("[0-9]+")) splits the original string into an array of strings. The separator is any sequence of numbers (numbers aren't allowed so they serve as separators). Then, a stream is created so I can apply functional operations and transformations.
.filter(s -> s.matches("(.+)?[A-Z](.+)?")) keeps into the stream only strings that have at least one upper-case letter.
.sorted((s1, s2) -> s2.length() - s1.length()) sorts the stream by length (desc).
.findFirst() tries to get the first string of the stream.
.orElse("") returns an empty string if no string was found.
.length(); gets the length of the string.
I suggest that you split your String to have an array of strings without digit:
yourString.split("[0-9]")
Then iterate over this array (says array a) to get the longest string that contains one Upper case character:
a[i].matches("[a-z]*[A-Z]{1}[a-z]*");
You can use a simple array. The algorithm to use would be a dynamic sliding window. Here is an example of a static sliding window: What is a Sliding Window
The algorithm should be as follows:
Keep track of 2 indexes of the array of char. These 2 indexes will be referred to as front and back here, representing the front and back of the array.
Have an int (I'll name it up here) to keep track of the number of upper case char.
Set all to 0.
Use a while loop that terminates if front > N where N is the number of char given.
If the next char is not a number, add 1 to front. Then check if that char is upper case. If so, add 1 to up.
If up is at least 1, update the maximum length if necessary.
If the next char is a number, continue checking the following char if they are also numbers. Set front to the first index where the char is not a number and back to front-1.
Output the maximum length.
You can use my solution which runs in O(n) time and finds the longest part without any digit and with a capital letter:
String testString = "skjssldfkjsakdfjlskdssfkjslakdfiop7adfaijsldifjasdjfil8klsasdfŞdijpfjapodifjpoaidjfpoaidjpfi9a";
int startIndex = 0;
int longestStartIndex = 0;
int endIndex = 0;
int index = 0;
int longestLength = Integer.MIN_VALUE;
boolean foundUpperCase = false;
while(index <= testString.length()) {
if (index == testString.length() || Character.isDigit(testString.charAt(index))) {
if (foundUpperCase && index > startIndex && index - startIndex > longestLength) {
longestLength = index - startIndex;
endIndex = index;
longestStartIndex = startIndex;
}
startIndex = index + 1;
foundUpperCase = false;
} else if (Character.isUpperCase(testString.charAt(index))) {
foundUpperCase = true;
}
index++;
}
System.out.println(testString.substring(longestStartIndex, endIndex));
You don't need regular expressions. Just use a few integers to act as index pointers into the string:
int i = 0;
int longestStart = 0;
int longestEnd = 0;
while (i < s.length()) {
// Skip past all the digits.
while (i < s.length() && Character.isDigit(s.charAt(i))) {
++i;
}
// i now points to the start of a substring
// or one past the end of the string.
int start = i;
// Keep a flag to record if there is an uppercase character.
boolean hasUppercase = false;
// Increment i until you hit another digit or the end of the string.
while (i < s.length() && !Character.isDigit(s.charAt(i))) {
hasUppercase |= Character.isUpperCase(s.charAt(i));
++i;
}
// Check if this is longer than the longest so far.
if (hasUppercase && i - start > longestEnd - longestStart) {
longestEnd = i;
longestStart = start;
}
}
String longest = s.substring(longestStart, longestEnd);
Ideone demo
Whilst more verbose than regular expressions, this has the advantage of not creating any unnecessary objects: the only object created is the longest string, right at the end.
I am using modification of Kadane algorithm to search the required password length. You may use isNumeric() and isCaps() function or include inline if statements. I have shown below with functions.
public boolean isNumeric(char x){
return (x>='0'&&x<='9');
}
public boolean isCaps(char x){
return (x>='A'&&x<='Z');
}
public int maxValidPassLen(String a)
{
int max_so_far = 0, max_ending_here = 0;
boolean cFlag = false;
int max_len = 0;
for (int i = 0; i < a.length(); i++)
{
max_ending_here = max_ending_here + 1;
if (isCaps(a.charAt(i))){
cFlag = true;
}
if (isNumeric(a.charAt(i))){
max_ending_here = 0;
cFlag = false;
}
else if (max_so_far<max_ending_here){
max_so_far = max_ending_here;
}
if(cFlag&&max_len<max_so_far){
max_len = max_so_far;
}
}
return max_len;
}
Hope this helps.
There are plenty of good answers here but thought it might be of interest to add one that uses Java 8 streams:
IntStream.range(0, s.length()).boxed()
.flatMap(b -> IntStream.range(b + 1, s.length())
.mapToObj(e -> s.substring(b, e)))
.filter(t -> t.codePoints().noneMatch(Character::isDigit))
.filter(t -> t.codePoints().filter(Character::isUpperCase).count() == 1)
.mapToInt(String::length).max();
If you wanted the string (rather than just the length), then the last line can be replaced with:
.max(Comparator.comparingInt(String::length));
Which returns an Optional<String>.
I'd use Streams and Optionals:
public static String getBestPassword(String password) throws Exception {
if (password == null) {
throw new Exception("Invalid password");
}
Optional<String> bestPassword = Stream.of(password.split("[0-9]"))
.filter(TypeErasure::containsCapital)
.sorted((o1, o2) -> o1.length() > o2.length() ? 1 : 0)
.findFirst();
if (bestPassword.isPresent()) {
return bestPassword.get();
} else {
throw new Exception("No valid password");
}
}
/**
* Returns true if word contains capital
*/
private static boolean containsCapital(String word) {
return word.chars().anyMatch(Character::isUpperCase);
}
Be sure to write some unit tests
public String pass(String str){
int length = 0;
boolean uppercase = false;
String s= "";
String d= "";
for(int i=0;i<str.length();i++){
if(Character.isUpperCase(str.charAt(i)) == true){
uppercase = true;
s = s+str.charAt(i);
}else if(Character.isDigit(str.charAt(i)) == true ){
if(uppercase == true && s.length()>length){
d = s;
s = "";
length = s.length();
uppercase = false;
}
}else if(i==str.length()-1&&Character.isDigit(str.charAt(i))==false){
s = s + str.charAt(i);
if(uppercase == true && s.length()>length){
d = s;
s = "";
length = s.length();
uppercase = false;
}
}else{
s = s+str.charAt(i);
}
}
return d;}
Here is a simple solution with Scala
def solution(str: String): Int = {
val strNoDigit = str.replaceAll("[0-9]", "-")
strAlphas = strNoDigit.split("-")
Try(strAlphas.filter(_.trim.find(_.isUpper).isDefined).maxBy(_.size))
.toOption
.map(_.length)
.getOrElse(-1)
}
Another solution using tail recursion in Scala
def solution2(str: String): Int = {
val subSt = new ListBuffer[Char]
def checker(str: String): Unit = {
if (str.nonEmpty) {
val s = str.head
if (!s.isDigit) {
subSt += s
} else {
subSt += '-'
}
checker(str.tail)
}
}
checker(str)
if (subSt.nonEmpty) {
val noDigitStr = subSt.mkString.split("-")
Try(noDigitStr.filter(s => s.nonEmpty && s.find(_.isUpper).isDefined).maxBy(_.size))
.toOption
.map(_.length)
.getOrElse(-1)
} else {
-1
}
}
This is a dynamic programming problem. You can solve this yourself using a matrix. It is easy enough. Just give it a try. Take the characters of the password as the rows and columns of the matrix. Add the diagonals if the current character appended to the last character forms a valid password. Start with the smallest valid password as the initial condition.
String[] s = testString.split("[0-9]");
int length = 0;
int index = -1;
for(int i=0; i< s.length; i++){
if(s[i].matches("[a-z]*.*[A-Z].*[a-z]*")){
if(length <= s[i].length()){
length = s[i].length();
index = i;
}
}
}
if(index >= 0){
System.out.println(s[index]);
}
//easiest way to do it:
String str = "a0Ba12hgKil8oPlk";
String[] str1 = str.split("[0-9]+");
List<Integer> in = new ArrayList<Integer>();
for (int i = 0; i < str1.length; i++) {
if (str1[i].matches("(.+)?[A-Z](.+)?")) {
in.add(str1[i].length());
} else {
System.out.println(-1);
}
}
Collections.sort(in);
System.out.println("string : " + in.get(in.size() - 1));
This is my solution with c#. I tested a range of strings and it gave me the correct value. Used Split. No Regex or Substrings. Let me know if it works; open to improvements and corrections.
public static int validPassword(string str)
{
List<int> strLength = new List<int>();
if (!(str.All(Char.IsDigit)))
{
//string str = "a0Bb";
string[] splitStrs = str.Split(new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' });
//check if each string contains a upper case
foreach (string s in splitStrs)
{
//Console.WriteLine(s);
if (s.Any(char.IsUpper) && s.Any(char.IsLower) || s.Any(char.IsUpper))
{
strLength.Add(s.Length);
}
}
if (strLength.Count == 0)
{
return -1;
}
foreach (int i in strLength)
{
//Console.WriteLine(i);
}
return strLength.Max();
}
else
{
return -1;
}
}
I think this solution takes care of all the possible corner cases. It passed all the test cases in an Online Judge. It is a dynamic sliding window O(n) solution.
public class LongestString {
public static void main(String[] args) {
// String testString = "AabcdDefghIjKL0";
String testString = "a0bb";
int startIndex = 0, endIndex = 0;
int previousUpperCaseIndex = -1;
int maxLen = 0;
for (; endIndex < testString.length(); endIndex++) {
if (Character.isUpperCase(testString.charAt(endIndex))) {
if (previousUpperCaseIndex > -1) {
maxLen = Math.max(maxLen, endIndex - startIndex);
startIndex = previousUpperCaseIndex + 1;
}
previousUpperCaseIndex = endIndex;
} else if (Character.isDigit(testString.charAt(endIndex))) {
if (previousUpperCaseIndex > -1) {
maxLen = Math.max(maxLen, endIndex - startIndex);
}
startIndex = endIndex + 1;
previousUpperCaseIndex = -1;
}
}
if (previousUpperCaseIndex > -1)
maxLen = Math.max(maxLen, endIndex - startIndex);
System.out.println(maxLen);
}}
function ValidatePassword(password){
var doesContainNumber = false;
var hasUpperCase = false;
for(var i=0;i<password.length;i++){
if(!isNaN(password[i]))
doesContainNumber = true;
if(password[i] == password[i].toUpperCase())
hasUpperCase = true;
}
if(!doesContainNumber && hasUpperCase)
return true;
else
return false;
}
function GetLongestPassword(inputString){
var longestPassword = "";
for(var i=0;i<inputString.length-1;i++)
{
for (var j=i+1;j<inputString.length;j++)
{
var substring = inputString.substring(i,j+1);
var isValid = ValidatePassword(substring);
if(isValid){
if(substring.length > longestPassword.length)
{
longestPassword = substring;
}
}
}
}
if(longestPassword == "")
{
return "No Valid Password found";
}
else
{
return longestPassword;
}
}

implement basic string compression

I am working on question 1.5 from the book Cracking The Coding interview. The problem is to take a string "aabcccccaaa" and turn it into a2b1c5a3.
If the compressed string is not smaller than the original string, then return the original string.
My code is below. I used an ArrayList because I would not know how long the compressed string would be.
My output is [a, 2, b, 1, c, 5], aabc, []. When the program gets to the end of string, it doesn't have a character to compare the last character too.
import java.util.*;
import java.io.*;
public class stringCompression {
public static void main(String[] args) {
String a = "aabcccccaaa";
String b = "aabc";
String v = "aaaa";
check(a);
System.out.println("");
check(b);
System.out.println("");
check(v);
}
public static void check(String g){
ArrayList<Character> c = new ArrayList<Character>();
int count = 1;
int i = 0;
int h = g.length();
for(int j = i + 1; j < g.length(); j++)
{
if(g.charAt(i) == g.charAt(j)){
count++;
}
else {
c.add(g.charAt(i));
c.add((char)( '0' + count));
i = j;
count = 1;
}
}
if(c.size() == g.length()){
System.out.print(g);
}
else{
System.out.print(c);
}
}
}
In the last loop you're not adding the result to the array. When j = g.length() still needs to add the current char and count to the array. So you could check the next value of j before increment it:
for(int j = i + 1; j < g.length(); j++)
{
if(g.charAt(i) == g.charAt(j)){
count++;
}
else {
c.add(g.charAt(i));
c.add((char)( '0' + count));
i = j;
count = 1;
}
if((j + 1) = g.length()){
c.add(g.charAt(i));
c.add((char)( '0' + count));
}
}
I would use a StringBuilder rather than an ArrayList to build your compressed String. When you start compressing, the first character should already be added to the result. The count of the character will be added once you've encountered a different character. When you've reached the end of the String you should just be appending the remaining count to the result for the last letter.
public static void main(String[] args) throws Exception {
String[] data = new String[] {
"aabcccccaaa",
"aabc",
"aaaa"
};
for (String d : data) {
System.out.println(compress(d));
}
}
public static String compress(String str) {
StringBuilder compressed = new StringBuilder();
// Add first character to compressed result
char currentChar = str.charAt(0);
compressed.append(currentChar);
// Always have a count of 1
int count = 1;
for (int i = 1; i < str.length(); i++) {
char nextChar = str.charAt(i);
if (currentChar == nextChar) {
count++;
} else {
// Append the count of the current character
compressed.append(count);
// Set the current character and count
currentChar = nextChar;
count = 1;
// Append the new current character
compressed.append(currentChar);
}
}
// Append the count of the last character
compressed.append(count);
// If the compressed string is not smaller than the original string, then return the original string
return (compressed.length() < str.length() ? compressed.toString() : str);
}
Results:
a2b1c5a3
aabc
a4
You have two errors:
one that Typo just mentioned, because your last character was not added;
and another one, if the original string is shorter like "abc" with only three chars: "a1b1c1" has six chars (the task is "If the compressed string is not smaller than the original string, then return the original string.")
You have to change your if statement, ask for >= instead of ==
if(c.size() >= g.length()){
System.out.print(g);
} else {
System.out.print(c);
}
Use StringBuilder and then iterate on the input string.
private static string CompressString(string inputString)
{
var count = 1;
var compressedSb = new StringBuilder();
for (var i = 0; i < inputString.Length; i++)
{
// Check if we are at the end
if(i == inputString.Length - 1)
{
compressedSb.Append(inputString[i] + count.ToString());
break;
}
if (inputString[i] == inputString[i + 1])
count++;
else
{
compressedSb.Append(inputString[i] + count.ToString());
count = 1;
}
}
var compressedString = compressedSb.ToString();
return compressedString.Length > inputString.Length ? inputString : compressedString;
}

Look for repeated characters in a string

I know this question was asked many times, but I didn't find any of the answers helpful in my case. I have a method that receives a String. I want to check if any of the characters in the string are repeated. If so the method will return an empty String. If not it will return the String back.
The method is looking for any repeated character in the String.
private String visit(String word) {
int count = 0;
if(word == ""){
return "<empty>";
}
//alphabet is an array that holds all characters that could be used in the String
for(int i = 0; i < alphabet.length; i++){
for(int j = 0; j < word.length(); j++){
if(alphabet[i] == word.charAt(j)){
count++;
}
if(count == 2){
return "";
}
}
count = 0;
}
return word;
}
Ok, I publish my solution to this:
package main;
import java.util.Arrays;
public class main {
public static void main(String[] args) {
System.out.println(hasDups("abc"));
System.out.println(hasDups("abcb"));
}
public static String hasDups(String arg) {
String[] ar = arg.split("");
Arrays.sort(ar);
boolean noDups = true;
for (int i = 1; i < ar.length && noDups; i++) {
if (ar[i].equals(ar[i-1])) noDups = false;
}
if (noDups) return arg; else return "";
}
}
This might not be the best way of doing what you want, but you can use two for loops to check each character against all the other characters to see if it is repeated.
public static String hasRepeated(String word) {
if (word.isEmpty()) return "<empty>";
char[] charArray = word.toCharArray();
for (int i = 0; i < charArray.length; i++) {
for (int j = 0; j < charArray.length; j++) {
if (i == j) {
} else if (Character.toString(charArray[i]).
equalsIgnoreCase(Character.toString(charArray[j]))) {
return "";
}
}
}
return word;
}
Note: This code assumes that the case of the character doesn't matter, it just checks if it is repeated.
/**
* Returns the index of the first character repeated, or -1 if no repeats
*/
public static int firstRepeated( String s ) {
if ( s != null ) {
int n = s.length();
for (int i = 0; i < (n - 1); i++) {
int indx = s.indexOf( s.charAt( i ), i + 1 );
if ( indx > 0 ) {
return i;
}
}
}
return -1;
}
This works!!
public static String checkDuplicate(String str)
{
int count = 0;
char[] charArray = str.toCharArray();
for(int i=0;i<charArray.length;i++)
{
count = 0;
for(int j=0;j<charArray.length;j++)
{
if(charArray[i]==charArray[j])
{
count++;
if(count==2) break;
}
}
if(count==2) break;
}
if(count==2)
return "";
else
return str;
}
}

A string blowup method

I am trying to make a method that returns a version of the original string as follows: each digit 0-9 that appears in the original string is replaced by that many occurrences of the character to the right of the digit. So the string "a3tx2z" yields "attttxzzz", and "12x" yields "2xxx". A digit not followed by a character (i.e. at the end of the string) is replaced by nothing.
I've written the code but it only works for just the first digit and remains unchanged for the next ones.
public String blowUp( String str ){
StringBuffer buffer = null;
String toAdd = null;
String toReturnString = null;
if( str.length() == 0 ){
return "no string found";
}else{
for( int count = 0; count < str.length(); count++ ){
char c = str.charAt( count );
if( count == str.length() - 1 ){
if( Character.isDigit( c ) ){
return str.substring( 0, count );
}else{
return str;
}
}else if( Character.isDigit( c ) ){
char next = str.charAt( count + 1 );
buffer = new StringBuffer();
int nooftimes = Integer.parseInt(Character.toString( c ));
for( int j = 0; j < nooftimes; j++ ){
buffer.append( next );
}
toAdd = buffer.toString();
toReturnString = str.substring( 0, count ) + toAdd + str.substring( count + 1 );
return toReturnString;
}
}
return toReturnString;
}
// return toReturnString;
}
See the comments.
public String blowUp(String str) {
StringBuffer buffer = new StringBuffer();
// String toAdd = null;
// String toReturnString = null;
if (str.length() == 0) {
return "no string found";
} else {
for (int count = 0; count < str.length(); count++) {
char c = str.charAt(count);
/*
* if (count == str.length() - 1) {
*
* if (Character.isDigit(c)) {
*
* return str.substring(0, count); } else {
*
* return str; } } else
*/
if (Character.isDigit(c) && count < str.length()-1) {
char next = str.charAt(count + 1);
if (!Character.isDigit(next)) { // append only if next
// character isn't digit
// buffer = new StringBuffer();
int nooftimes = Integer.parseInt(Character.toString(c));
for (int j = 0; j < nooftimes; j++) {
buffer.append(next);
}
} else {
buffer.append(str.charAt(count+1)); // append digit followed by another digit with next digit
}
// toAdd = buffer.toString();
// toReturnString = str.substring(0, count) + toAdd
// + str.substring(count + 1);
} else {
buffer.append(c); // simply append if not digit
}
}
return buffer.toString();
}
// return toReturnString;
}
It looks like you're making this more complicated than it has to be, and in the process getting the logic a bit confused.
In pseudocode, this problem basically boils down to the following:
for every character 'c' in the input, starting from the first:
if c is not a digit:
add c to the output
otherwise (i.e. if c is a digit), if c is not the last character in the input:
let 'x' be the number represented by c
let 'n' be the next character in the input after c
add x copies of n to the output
return the output
I'll leave translating that into Java to you*.
* EDIT: or to #TheKojuEffect!
There are no less than 5 return points in your code, this is really, really bad. It makes it impossible to accurately determine what is going on in your code.
I'm old school, so I believe in one entry point and one exit point for any method, it makes it SO much easier to figure out what's going on...
Let's start with...
if( str.length() == 0 ){
return "no string found";
This should actually be returning the original String unchanged...don't you think...
if( count == str.length() - 1 ){
if( Character.isDigit( c ) ){
return str.substring( 0, count );
}else{
return str;
}
I can't even figure out why you would need this. The last character is no more special than the first, apart from the fact that if it's a digit, you should ignore it...
char next = str.charAt( count + 1 );
buffer = new StringBuffer();
int nooftimes = Integer.parseInt(Character.toString( c ));
for( int j = 0; j < nooftimes; j++ ){
buffer.append( next );
}
toAdd = buffer.toString();
toReturnString = str.substring( 0, count ) + toAdd + str.substring( count + 1 );
return toReturnString;
Then your return here! But you've only entered this section of code once! What about the rest of the String?
You also seem to be ignoring all the other characters in the String from what I can tell...
A simpler idea would be to use the StringBuffer (or StringBuilder as I prefer) and keep appending the resulting values to it, for example...
public static String blowUp(String str) {
StringBuilder sb = new StringBuilder(128);
for (int count = 0; count < str.length(); count++) {
char c = str.charAt(count);
if (Character.isDigit(c) && count < str.length() - 1) {
char next = str.charAt(count + 1);
int nooftimes = Integer.parseInt(Character.toString(c));
for (int j = 0; j < nooftimes; j++) {
sb.append(next);
}
count++;
} else if (!Character.isDigit(c)) {
sb.append(c);
}
}
return sb.toString();
}
Example input output
If I input...
a3tx2z
12x
a3tx2z1
12x1
I get
atttxzz
2x
atttxzz
2x
as output
#MadProgrammer I modified a little bit based on your code.
public String blowup(String str) {
StringBuilder sb = new StringBuilder();
for(int i =0; i < str.length(); i++) {
char c = str.charAt(i);
if(Character.isDigit(c) && i < str.length()-1) {
char next = str.charAt(i+1);
if(!Character.isDigit(next)) {
int repTimes = Integer.parseInt(Character.toString(c));
for(int k = 0; k < repTimes; k++) {
sb.append(next);
}
}
else {
sb.append(c);
}
}
else {
sb.append(c);
}
}
return new String(sb);
}

Count Character Consecutively in Java

I'm trying to write a method that returns the number of times char c first appears consecutively in s, even if it's a single occurrence of the character. Even spaces break the consecutive count. So the string "I'm bad at programming." should only return 1, if char c was 'a'.
The code below compiles but doesn't print the correct answers. Just something to show my general logic when it comes to approaching this problem.
public class WordCount
{
public int countRun( String s, char c )
{
int counter = 0;
for( int i = 0; i < s.length(); i++)
/*There should be other conditions here that checks for first
appearance consecutively. I've tried my fair share, but no
luck on getting correct results.*/
{
if( s.charAt(i) == c )
{
counter += 1;
}
}
return counter;
}
public static void main( String args[] )
{
WordCount x = new WordCount();
System.out.println( x.countRun( "Add dog", 'd' ) ); //should return 2
System.out.println( x.countRun( "Add dog", 'D' ) ); //should return 0
System.out.println( x.countRun( "Hope you're happy", 'p' )); //should return 1
System.out.println( x.countRun( "CCCCCcccC", 'C' )); //should return 5
}
}
I just need a few pointers (logic-wise or code). Maybe there's a method for Strings that I've never seen before that could make my program much simpler. I have very limited knowledge in programming and in Java.
EDIT: For anyone wondering if this is part of some homework assignment or whatnot, this was a question from a very old midterm. I got it wrong but for some reason but never bothered to ask for the correct answer at the time. I looked at it today and wanted to see if I knew the answer. Looks like I don't.
You could do it in one line:
int result = s.replaceFirst(".*?(" + c + "+).*", "$1").length();
This code uses regex to essentially extract the part of s that is the first contiguous occurrences of c, then gets the length of that.
This will also work for no occurrences, yielding zero.
See live demo.
Add a flag, and break out of the loop when you have found one matching character, then find "anything else". Maybe not the most compact or elegant, but true to the original code. Tested, and produces 2,0,1,5 as expected.
public int countRun( String s, char c )
{
int counter = 0;
boolean foundOne = false;
for( int i = 0; i < s.length(); i++)
{
if( s.charAt(i) == c )
{
counter += 1;
foundOne = true;
}
else {
if(foundOne) break;
}
}
return counter;
}
It occurs to me that counter>0 is an equivalent condition to foundOne==true; that would allow you to simplify the code to:
public int countRun( String s, char c )
{
int counter = 0;
for( int i = 0; i < s.length(); i++)
{
if( s.charAt(i) == c ) counter++;
else if(counter>0) break;
}
return counter;
}
The logic is a tiny bit harder to follow this way, as the variable name foundOne is self-documenting. But per other posts, "small is beautiful" too...
Using assci array counter
public static int countRun(String s, char c) {
int[] counts = new int[256];
int count = 0;
char currChar;
for (int i = 0; i < s.length(); i++) {
currChar = s.charAt(i);
if (currChar == c) {// match
counts[c]++;
} else if (Character.isSpaceChar(currChar)) {
counts[c] = 0;// reset counter for c
} else {// no match
if (counts[c] > 0) {// return accumulated counts if you have
count = counts[c];
return count;
}
}
}
return count;
}
public class A3B2C1 {
public static void main(String[] args) {
String s = "AAABBC";
s = s + '#';//dummy char to consider the last char 'C' in the string
//without using charAt()
int count = 1;
String n="";
int i=0;
StringBuffer bf = new StringBuffer();
char c[] = s.toCharArray();
for(i=0;i< c.length-1;i++)
{
if(c[i] == c[i+1])
{
count++;
}
else
{
n = c[i] +""+count;
bf.append(n);
count=1;
}
}
System.out.println("Output: "+bf);//prints-->> Output: A3B2C1
}
}

Categories