I have problem with my algorithm, I tried with my sample data noted below. And I don't understand why the result is not what I thought at all. For example when i = 3(n) and j = 2(n). The q should have output 2 but it's equal to 1. I guess the cause could just be that the while loop working was having problems. But I don't know the reason why. Please someone help me! Thank you very much
Running method
public static void compareStringToString(String str1, String str2) {
ArrayList<Integer> numSames = new ArrayList<Integer>();
int p = 0, n; // p - Maximum number of similar characters, n - the number of characters of the longer string
// str1 = "slcnsicnn"
// str2 = "ahnscnn"
int i = 0, j = 0;
if (str1.length() >= str2.length()) {
n = str1.length();
for (i = 0; i < n; i++) {
for (j = 0; j < str2.length(); j++) {
if (str1.charAt(i) == str2.charAt(j)) {
p = 0;
while (str1.charAt(i + p) == str2.charAt(j + p)) {
p++;
if ((i + p < n) || (j + p < str2.length())) {
break;
}
}
numSames.add(p);
}
}
}
System.out.println("The similarity of the two strings is: " + (((float)
Collections.max(numSames)) / n) * 100 + "%");
else {
n = str2.length();
// TODO Same things
}
Running Screen
**
I did as you said. I created a new method to split the work. Indeed, when I did that, my mind became clearer. And more specifically, I was able to run it smoothly without errors. Or maybe there are some more minor bugs that I haven't noticed yet. But it's really great like a little bit of a burden. Once again thank you very much for your kind advice.
**
// Get the number of similar characters after a pair of similar characters of 2 strings
public static int getNumSimilarAfterChar(String str1, String str2, int indexStr1, int indexStr2) {
int numChar = 0; // It's both a count and an index
// Substrings to work with algorithm
String subStr1;
String subStr2;
if (str1.charAt(indexStr1) == str2.charAt(indexStr2)) {
// Cut substring from highlighted part
subStr1 = str1.substring(indexStr1);
subStr2 = str2.substring(indexStr2);
while (subStr1.charAt(numChar) == subStr2.charAt(numChar)) {
numChar++;
if ((numChar >= (subStr1.length() - 1)) || (numChar >= (subStr2.length() - 1))) {
break;
}
}
return numChar + 1;
} else {
return numChar;
}
}
// Given any two strings of characters, compare the match of these two strings
/**
* Compare the match of string 1 vs string 2
*
* #param str1
* #param str2
*/
public static void compareStringToString(String str1, String str2) {
ArrayList<Integer> numSames = new ArrayList<Integer>();
// maxSimilar - maximum number of similar characters, totalLength - the number of characters of longer string
int numSimilar = 0, totalLength;
// slcnsicnn
// ahnscnn
int i = 0, j = 0;
// If string 1 is longer than string 2
if (str1.length() >= str2.length()) {
totalLength = str1.length();
for (i = 0; i < totalLength; i++) {
for (j = 0; j < str2.length(); j++) {
// Browse until you come across two similar characters
if (str1.charAt(i) == str2.charAt(j)) {
numSimilar = MyStrings.getNumSimilarAfterChar(str1, str2, i, j);
numSames.add(numSimilar);
System.out.println(numSames.toString());
}
}
}
// Get the max value in a list of how many identical characters are generated
System.out.println("The similarity of the two strings is: " + (((float) Collections.max(numSames)) / totalLength) * 100 + "%");
} else {
totalLength = str2.length();
// TODO Same things
}
}
So trying to create a method which goes through a string and checks each char for vowels.
However when it reaches the end and does a forward check for the char. i get a strings out of bound exception. i tried adding a check for whitespace for the char ahead but still get the exception.
for (char i = 0; i < buffer.length; i++) {
if (isVowel(key.charAt(i + 1)) && !Character.isWhitespace(key.charAt(i + 1)) {
buffer[i] = key.charAt(i);
} else {
break;
}
}
Create the buffer for a correct size like
char[] keyChar = key.toCharArray();
char[] buffer = new char[keyChar.length]; //same size
Then, iterate the key, not the buffer
for(int i = 0; i < keyChar.length -1; ++i)
And don't go to the end since you use [i + 1] in the logic.
Note that this will ignore the last character, you have to see if you want that last character or not in the buffer. If so, you will need to add it (without your check on the next one obviously)
for (char i = 0; i < buffer.length-1; i++) {
if (isVowel(key.charAt(i + 1)) && !key.charAt(i + 1) && !Character.isWhitespace(key.charAt(i + 1)) {
buffer[i] = key.charAt(i);
} else {
break;
}
}
I'm trying to set up a compression algorithm that places a number before a char in a string when that char can be seen in succession. EX: for the string
"balloonnnnns" it would be compressed to "ba2l2o5n" but I am receiving an index out of bounds error:
for(int i = 0; i < (length-1); i++ ){
if (original.charAt(i) == original.charAt(i + 1)){
count = count + 1;
original = original.substring(i, i+1);
System.out.println(original);
System.out.println(count);
if(count > 0){
altered = count + original.substring(i);
System.out.println(altered);
}
}else{
count = 0;
As #Jon Skeet pointed out you shouldn't change your original while in the loop.
You could try this way (comments on code for understanding)
Test:
public class Test
{
public static void main ( String [ ] args )
{
String original = "balloonnnnns";
int length = original.length ( );
int count = 1;
String altered = "";
//Loop over all string
for(int i = 0; i < (length-1); i++ ){
//while they are the same
while (original.charAt(i) == original.charAt(i + 1)){
//count and keep going on the original string
count++;
i++;
//avoid border case when last character is repeated, i.e : baaaaaaaa
if ( i == length -1)
{
break;
}
}
//if they are repetead
if(count > 1)
{
//add altered + count + charRepeated, i.e. a3e5t
altered = altered +count + original.charAt(i);
}
else{
//just add the normal character without count
altered += original.charAt(i);
}
//add last character if not repeated
if ( (i == length - 2) && (count > 1))
{
altered += original.charAt ( i+1 );
}
//reset counting
count = 1;
}
System.out.println ( altered );
}
}
Output:
ba2l2o5ns
The first time your loop gets executed, you update string named 'original' with the first character of actual 'original' string.
For eg. if String original = "aaa" - after loop executes for 0, value for original becomes 'a'!
You can refer this for solutions:
Java compressing Strings
This code supposed to output the longest run on which a character in a string has a consecutive runs of itself. Though the problem is that it outputs: 8 (which should be 5 instead). I just would like to ask what seems to be the problem regarding this code.
public class Sample {
public static void main(String[] args) {
String setofletters = "aaakkcccccczz"; /* 15 */
int output = runLongestIndex(setofletters);
System.out.println("Longest run that first appeared in index:" + output);
}
public static int runLongestIndex(String setofletters) {
int ctr = 0;
int ctrstor = 0;
int ii = 0;
int output = 0;
// loops until the last character in the string
for (int i = 0; i < setofletters.length() - 1; i++) {
// checks if the letter is the same to the next
if (setofletters.charAt(i) == setofletters.charAt(i++)) {
ctr++;
ii = i++;
// loops until the letter in the index is no longer equal
while (setofletters.charAt(i) == setofletters.charAt(ii)) {
ii++;
ctr++;
}
if (ctr > ctrstor) {
output = i;
}
// storing purposes
ctrstor = ctr;
}
// resets the counter
ctr = 0;
}
return output;
}
}
UPDATE Sorry, I misunderstood your question a bit, you need to make the following changes in your code to make it work.(lines with comments)
public static int runLongestIndex(String setofletters){
int ctr = 1; // every character is repeated at least once, so you should initialize it to 1, not 0
int ctrstor = 0;
int ii = 0;
int output = 0;
for (int i = 0; i < setofletters.length() - 1; i++) {
if (i < setofletters.length() - 1 && setofletters.charAt(i) == setofletters.charAt(i+1)) { // i++ is not same as i+1
ctr++;
ii = i+1; // i++ is not same as i+1
while (setofletters.charAt(i) == setofletters.charAt(ii)) {
ii++;
ctr++;
}
if (ctr > ctrstor) {
output = i;
}
ctrstor = ctr;
}
ctr = 1; // for the same reason I mentioned above
}
return output;
}
EDIT : the easiest way to write your code is :
public static int runLongestIndex(String setofletters){
int ctr = 1;
int output = 0;
int j=0;
for(int i=0; i<setofletters.length()-1;i++){
j=i;
while(i <setofletters.length()-1 && setofletters.charAt(i)==setofletters.charAt(i+1)){
i++;
ctr++;
}
if(ctr>output){
output=j;
}
ctr = 1;
}
return output;
}
Why are you assigning i to output? You should assign ctr to output.
change
if(ctr>ctrstor){
output=i;
}
to
if(ctr>ctrstor){
output=ctr;
}
and also I think you should change
if(setofletters.charAt(i)==setofletters.charAt(i++))
to
if(i<setofletters.length()-1 && setofletters.charAt(i)==setofletters.charAt(i+1)){
and you should intialize ctr to 1 but not 0 because every character is repeated at least once.
I'll give you a Scala implementation for that problem.
Here it is the automatic test (in BDD style with ScalaTest)
import org.scalatest._
class RichStringSpec extends FlatSpec with MustMatchers {
"A rich string" should "find the longest run of consecutive characters" in {
import Example._
"abceedd".longestRun mustBe Set("ee", "dd")
"aeebceeedd".longestRun mustBe Set("eee")
"aaaaaaa".longestRun mustBe Set("aaaaaaa")
"abcdefgh".longestRun mustBe empty
}
}
Following is the imperative style implementation, with nested loops and mutable variables as you would normally choose to do in Java or C++:
object Example {
implicit class RichString(string: String) {
def longestRun: Set[String] = {
val chunks = mutable.Set.empty[String]
val ilen = string.length
var gmax = 0
for ((ch, curr) <- string.zipWithIndex) {
val chunk = mutable.ListBuffer(ch)
var next = curr + 1
while (next < ilen && string(next) == ch) {
chunk += string(next)
next = next + 1
}
gmax = chunk.length max gmax
if (gmax > 1) chunks += chunk.mkString
}
chunks.toSet.filter( _.length == gmax )
}
}
}
Following is a functional-style implementation, hence no variables, no loops but tail recursion with result accumulators and pattern matching to compare each character with the next one (Crazy! Isn't it?):
object Example {
implicit class RichString(string: String) {
def longestRun: Set[String] = {
def recurse(chars: String, chunk: mutable.ListBuffer[Char], chunks: mutable.Set[String]): Set[String] = {
chars.toList match {
case List(x, y, _*) if (x == y) =>
recurse(
chars.tail,
if (chunk.isEmpty) chunk ++= List(x, y) else chunk += y,
chunks
)
case Nil =>
// terminate recursion
chunks.toSet
case _ => // x != y
recurse(
chars.tail,
chunk = mutable.ListBuffer(),
chunks += chunk.mkString
)
}
}
val chunks = recurse(string, mutable.ListBuffer(), mutable.Set.empty[String])
val max = chunks.map(_.length).max
if (max > 0) chunks.filter( _.length == max ) else Set()
}
}
}
For example, for the given "aeebceeedd" string, both implementations above will build the following set of chunks (repeating characters)
Set("ee", "eee", "dd")
and they will filter those chunks having the maximum length (resulting "eee").
This code should work for any length of string sequence.
public class LongestStringSequqnce {
static String myString = "aaaabbbbcccchhhhiiiiibbbbbbbbbccccccc";
static int largestSequence = 0;
static char longestChar = '\0';
public static void main(String args[]) {
int currentSequence = 1;
char current = '\0';
char next = '\0';
for (int i = 0; i < myString.length() - 1; i++) {
current = myString.charAt(i);
next = myString.charAt(i + 1);
// If character's are in sequence , increase the counter
if (current == next) {
currentSequence += 1;
} else {
if (currentSequence > largestSequence) { // When sequence is
// completed, check if
// it is longest
largestSequence = currentSequence;
longestChar = current;
}
currentSequence = 1; // re-initialize counter
}
}
if (currentSequence > largestSequence) { // Check if last string
// sequence is longest
largestSequence = currentSequence;
longestChar = current;
}
System.out.println("Longest character sequence is of character "
+ longestChar + " and is " + largestSequence + " long");
}
}
Source : http://www.5balloons.info/program-java-code-to-find-longest-character-sequence-in-a-random-string/
if(ctr>ctrstor){
output=i;
}
//storing purposes
ctrstor=ctr;
This looks like the problem. So if you find 8 consecutive characters, it will set output to 8, and proceed. The next time thru, it finds 3 consecutive characters, so doesn't set output, but sets ctrstor. Next time thru it finds 4 consecutive characters, and this will set output to 4
There are few traps in the code that your logic felt in:
Code incorrectly assumes that there is always next character to compare current one.
This fails for string like "a" or the last character in any string.
Code does not store the max count of characters but only the max index (i).
MaxCount is needed to compare the next chars sequence size.
Loop for and loop while repeat the same subset of characters.
Also variable name style makes it harder to understand the code.
After correcting above
public static int runLongestIndex(String setofletters) {
int maxCount = 0;
int maxIndex = 0;
// loops each character in the string
for (int i = 0; i < setofletters.length() - 1; ) {
// new char sequence starts here
char currChar = setofletters.charAt(i);
int count = 1;
int index = i;
while ( (index < setofletters.length() - 1) &&
(currChar == setofletters.charAt(++index)) ) {
count++;
}
if (count > maxCount) {
maxIndex = i;
maxCount = count;
}
i = index;
}
return maxIndex;
}
See Java DEMO
I think you don't need an internal loop:
public static int runLongestIndex(String setofletters) {
if (setofletters == null || setofletters.isEmpty()) {
return -1;
}
int cnt = 1;
char prevC = setofletters.charAt(0);
int maxCnt = 1;
//char maxC = prevC;
int maxRunIdx = 0;
int curRunIdx = 0;
for (int i = 1; i < setofletters.length(); i++){
final char c = setofletters.charAt(i);
if (prevC == c) {
cnt++;
} else {
if (cnt > maxCnt) {
maxCnt = cnt;
//maxC = prevC;
maxRunIdx = curRunIdx;
}
cnt = 1;
curRunIdx = i;
}
prevC = c;
}
if (setofletters.charAt(setofletters.length() - 1) == prevC) {
if (cnt > maxCnt) {
//maxC = prevC;
maxCnt = cnt;
maxRunIdx = curRunIdx;
}
}
return maxRunIdx;
}
and this code:
System.out.println(runLongestIndex("aaakkcccccczz"));
gives you
5
This is how a "colleague" of mine is understanding to write readable code in order to solve this problem, even if this is working :)
public static int count (String str) {
int i = 0;
while(i < str.length()-1 && str.charAt(i)==str.charAt(i+1))
i ++;
return ++i;
}
public static int getLongestIndex(String str){
int output = 0;
for(int i=0, cnt = 1, counter = 0 ; i<str.length() - 1;i += cnt, cnt = count(str.substring(i)), output = (counter = (cnt > counter ? cnt : counter)) == cnt ? i : output);
return output;
}
int indexOfLongestRun(String str) {
char[] ar = str.toCharArray();
int longestRun = 0;
int lastLongestRun = 0;
int index = 0;
for(int i = ar.length-1; i>0; i--){
if(ar[i] == ar[i-1]){
longestRun++;
}else{
if(longestRun > lastLongestRun){
lastLongestRun = longestRun;
longestRun = 0;
index = i;
}
}
}
return index;
Well, the solution a bit depends on the additional requirements. Here is the code which returns the FIRST longest sequence of a repeated character int the given string, meaning if you have a second sequence with the same length you never get it out :(. But still, this is a simple and clear solution here, so good news - it works! :)
string = 'abbbccddddddddeehhhfffzzzzzzzzdddvyy'
longest_sequence = ''
for i in range(len(string)):
is_sequence = True
ch_sequence = ''
while is_sequence:
ch_sequence += string[i]
if i+1 < len(string) and string[i]==string[i+1]:
i += 1
else:
is_sequence = False
if len(ch_sequence) > len(longest_sequence):
longest_sequence = ch_sequence
print (longest_sequence)
#Paolo Angioletti already provided an answer using Scala, but it's more complicated than it needs to be. The idea is not very different from Run-length encoding. Time complexity O(n).
def longestConsecutive(s: String): (Char, Int) = {
Iterator.iterate(('\u0000', 0, 0)) { case (ch, longestRun, i) =>
val run = (i until s.length)
.takeWhile(s(_) == s(i))
.size
if (run > longestRun) (s(i), run, i + run)
else (ch, longestRun, i + run)
}
.dropWhile(i => s.isDefinedAt(i._3))
.take(1)
.map(x => (x._1, x._2))
.next()
}
Tested with:
("s", "ch", "n")
----------------
("", '\u0000', 0),
("a", 'a', 1),
("aabcddbbbea", 'b', 3),
("abcddbbb", 'b', 3),
("cbccca", 'c', 3)
#include <iostream>
#include<algorithm>
using namespace std;
int main() {
string s="abbcccccbbffffffffff";
//cin>>s;
int count=1;
int maxcount=1;
int start=0;
int ps=0;
for (int i=0;i<s.size()-1;i++)
{
if(s.at(i)==s.at(i+1))
{
count +=1;
maxcount=max(maxcount,count);
}
else
{
ps=max(ps,start+count);
count =1;
start=i;
}
}
for(int i=1;i<=maxcount;i++)
{
cout<<s.at(i+ps);
}
// your code goes here
return 0;
}
This is the simplest I can think of and it will print the number of the longest sequenced identical characters in a one line string.
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
scanner.close();
int count = 0;
int curCount = 1;
for (int i = 0; i < s.length() -1; i++) {
if (s.charAt(i) == s.charAt(i + 1)) {
curCount++;
if (curCount > count) {
count = curCount;
}
}else {
if (curCount > count) {
count = curCount;
}
curCount = 1;
}
}
System.out.println(count);
}
For example if the binary string is 10100010 then the program must return 1st,3rd and 7th i.e the positions of the 1's.
Below is the code which you are looking for note that regex starts with zeroth position.
String regex = "[1]";
String data = "10100010";
Matcher m = Pattern.compile(regex).matcher(data);
while(m.find())
{
System.out.println(m.group() + " => " + (m.start()+1) );
}
Two options:
Convert it to an integer/long (if possible) and then shift one bit each time and check if it's 1. For example:
String str = "10100010";
Integer x = Integer.valueOf(str);
int len = str.length();
while (x != 0) {
if (x & 0x1 == 1) {
System.out.println(len);
}
len--;
x >>= 1;
}
Scan the string by-index and check if its' value is 1:
for (int i = 0; i < str.length(); i++) {
if (str.chatAt(i) == '1') {
//print
}
}
char[] str="10100010".toCharArray();
for(int i=0;i<str.length;i++){
if(str[i]=='1'){
int setBit=1;
setBit+=i;
System.out.println(setBit+"th");
}
}