Java Decode RLE string - java

Example if i have an input like:
H9e3e2l5o
the output have to be:
Heeeeeeeeeeeellooooo
This is the code that I wrote so far:
public class RLE {
public static String decode(String st) {
char[] stArr = st.toCharArray();
char lastseen = 0;
StringBuilder sb = new StringBuilder();
for (char s : stArr) {
if (!Character.isDigit(s)) {
lastseen = s;
sb.append(s);
} else {
int n = Integer.parseInt(String.valueOf(s));
for (int i = 0; i < n - 1; i++) {
sb.append(lastseen);
}
}
}
return sb.toString();
}
Results in:
'H9e3e2l5o' -> HHHHHHHHHeeeeelllllo

I'm assuming generic variant, here is corrected version:
public static String decode(final String st) {
final StringBuilder sb = new StringBuilder();
final char[] chars = st.toCharArray();
int i = 0;
while (i < chars.length) {
int repeat = 0;
while ((i < chars.length) && Character.isDigit(chars[i])) {
repeat = repeat * 10 + chars[i++] - '0';
}
final StringBuilder s = new StringBuilder();
while ((i < chars.length) && !Character.isDigit(chars[i])) {
s.append(chars[i++]);
}
if (repeat > 0) {
for (int j = 0; j < repeat; j++) {
sb.append(s.toString());
}
} else {
sb.append(s.toString());
}
}
return sb.toString();
}
#Test
public void test() {
Assert.assertEquals("abb", decode("1a2b"));
Assert.assertEquals("aaaaaaaaaa", decode("10a"));
Assert.assertEquals("baaaaaaaaaa", decode("b10a"));
Assert.assertEquals("abab", decode("2ab"));
Assert.assertEquals("Heeeeeeeeeeeellooooo", decode("H9e3e2l5o"));
}

Related

The longest common subsequence for n string in java without using libraries?

I am trying to find a simple solution and I have read all the information or question that try to answer or have solve the problem , and i have being testing.
I have found a solution which i converted from c#, and it works, but is too complicated and i do not understand how it works, so i was trying to make my own solution.
public static String lcs(String[] strings) {
if (strings.length == 0)
return "0";
if (strings.length == 1)
return strings[0];
int max = -1;//max length of a string
int cacheSize = 1; //multiplied length size of array with each other.
for (int i = 0; i < strings.length; i++) {
cacheSize *= strings[i].length();
if (strings[i].length() > max)
max = strings[i].length();
}
String[] cache = new String[cacheSize];
int[] indexes = new int[strings.length];
for (int i = 0; i < indexes.length; i++)
indexes[i] = strings[i].length() - 1;
return lcsBack(strings, indexes, cache);
}
public static String lcsBack(String[] strings, int[] indexes, String[] cache) {
for (int i = 0; i < indexes.length; i++)
if (indexes[i] == -1)
return "";
boolean match = true;
for (int i = 1; i < indexes.length; i++) {
if (strings[0].charAt(indexes[0]) != strings[i].charAt(indexes[i])) {
match = false;
break;
}
}
if (match) {
int[] newIndexes = new int[indexes.length];
for (int i = 0; i < indexes.length; i++)
newIndexes[i] = indexes[i] - 1;
String result = lcsBack(strings, newIndexes, cache) + strings[0].charAt(indexes[0]);
cache[calcCachePos(indexes, strings)] = result;
return result;
} else {
String[] subStrings = new String[strings.length];
for (int i = 0; i < strings.length; i++) {
if (indexes[i] <= 0)
subStrings[i] = "";
else {
int[] newIndexes = new int[indexes.length];
for (int j = 0; j < indexes.length; j++)
newIndexes[j] = indexes[j];
newIndexes[i]--;
int cachePos = calcCachePos(newIndexes, strings);
if (cache[cachePos] == null)
subStrings[i] = lcsBack(strings, newIndexes, cache);
else
subStrings[i] = cache[cachePos];
}
}
String longestString = "";
int longestlength = 0;
for (int i = 0; i < subStrings.length; i++) {
if (subStrings[i].length() > longestlength) {
longestString = subStrings[i];
longestlength = longestString.length();
}
}
cache[calcCachePos(indexes, strings)] = longestString;
return longestString;
}
}
static int calcCachePos(int[] indexes, String[] strings) {
int factor = 1;
int pos = 0;
for (int i = 0; i < indexes.length; i++) {
pos += indexes[i] * factor;
factor *= strings[i].length();
}
return pos;
}
So on what i understand i have being able, to make this method which is simple, but still doesn't work.
And i know from readings that the best way to solve this is using dinamic programming I would appreciate if somebody can help, thank you
/**
* #param strArr .
* #return String
*/
public String findCommonString(String[] words) throws Exception {
try {
String commonStr = "";
String tempCom = "";
char[] longestWordChars = findTheLongestString(words).toCharArray();
for (char c : longestWordChars) {
tempCom += c;
for (String word : words) {
if (!word.contains(tempCom)) {
tempCom = Character.toString(c);
for (String word2 : words) {
if (!word2.contains(tempCom)) {
tempCom = "";
break;
}
}
break;
}
}
if (tempCom != "" && tempCom.length()>commonStr.length()) {
commonStr = tempCom;
//strArr = removeFirstOccurrence(strArr, tempCom);
// tempCom = "";
}
}
return commonStr;
} catch (Exception e) {
logger.warn("[findCommonString] [STATUS] - ERROR ");
logger.warn("[findCommonString] [EXCEPTION] " + e.getMessage());
throw e;
}
/**
* #param strArr .
* #return String
*/
public String findTheLongestString(String[] words) throws Exception { // test
try {
String longestWord = "";
for (String s : words) {
if (longestWord.length() < s.length()) {
longestWord = s;
}
}
return longestWord;
} catch (Exception e) {
logger.warn("[findTheLongestString] [STATUS] - ERROR ");
logger.warn("[findTheLongestString] [EXCEPTION] " + e.getMessage());
throw e;
}
}
I have being testing with this two test unit example
#Test
public void SubsequenceServiceTest3() throws Exception {
assertEquals("CDAC", subsequenceService.findCommonSequence(new String[] { "BCDAACD", "ACDBAC" }));
}
#Test
public void SubsequenceServiceTest14() throws Exception {
assertEquals("CA", subsequenceService.findCommonSequence(new String[] { "ACADB", "CBDA" }));
}

Maximum Repeating characters and count

I wanted to get the maximum repeating characters count and its relevant index. I am able to print the max repeating characters in a given string and its index. However I am unable to print the total count of repeating character. Below is my code
public class MaxRepeating {
static char charactercountIndex(String str) {
int len = str.length();
int count = 0;
char res = str.charAt(0);
for (int i = 0; i < len; i++) {
int cur_count = 0;
for (int j = i + 1; j < len; j++) {
if (str.charAt(i) != str.charAt(j))
break;
cur_count++;
}
if (cur_count > count) {
count = cur_count;
res = str.charAt(i);
}
}
return res;
}
public static void main(String args[]) {
String str = "aaaaaaccde";
char s1 = charactercountIndex(str);
str.indexOf(s1);
System.out.println(str.indexOf(s1));
System.out.println(charactercountIndex(str));
}
}
output should <0,6>
0 is the index of character a
6 is the total time character "a" present in the string
If you are open to a slightly different approach, there is a fairly straightforward way to do this using regex and streams. We can try splitting the input string into like-lettered substring components using the following regex:
(?<=(.))(?!\\1)
Then, we can use Collections.max to find the largest string in the collection, and finally use String#indexOf to find the index of that substring.
String str = "aaaabbddddddddddddddddddddaaccde";
List<String> parts = Arrays.asList(str.split("(?<=(.))(?!\\1)"));
String max = Collections.max(parts, Comparator.comparing(s -> s.length()));
System.out.println("largest substring: " + max);
int index = str.indexOf(max);
System.out.println("index of largest substring: " + index);
largest substring: dddddddddddddddddddd
index of largest substring: 6
I've done something like this:
static Entry<String, Integer> charactercountIndex(String str) {
HashMap<String, Integer> stringIntegerHashMap = new HashMap<>();
for (String letter : str.split("")) {
if (stringIntegerHashMap.containsKey(letter)) {
stringIntegerHashMap.put(letter, (stringIntegerHashMap.get(letter) + 1));
} else {
stringIntegerHashMap.put(letter, 1);
}
}
Entry<String, Integer> maxEntry = null;
for (Entry<String, Integer> entry : stringIntegerHashMap.entrySet()) {
if (maxEntry == null
|| entry.getValue().compareTo(maxEntry.getValue()) > 0) {
maxEntry = entry;
}
}
return maxEntry;
}
public static void main(String args[]) {
String str = "aaaabbddddddddddddddddddddaaccde";
Entry<String, Integer> s1 = charactercountIndex(str);
System.out.println(s1.getKey());
System.out.println(s1.getValue());
}
If you have any trouble, let me know.
You can return the result through a local class instance (which contains both the character and its occurrences). I added a local class CountResult.
By the way, I fixed your code (see // including ... comment).
You can try and check the working code below here.
public class MaxRepeating {
private static CountResult charactercountIndex(String str) {
int len = str.length();
char res = str.charAt(0);
int count = 0;
for (int i = 0; i < len; i++) {
int cur_count = 1; // including the tested char (first occurence)
for (int j = i + 1; j < len; j++) {
if (str.charAt(i) != str.charAt(j))
break;
cur_count++;
}
if (cur_count > count) {
res = str.charAt(i);
count = cur_count;
}
}
return new CountResult(res, count);
}
private static class CountResult {
private char maxChar;
private int count;
public CountResult(char maxChar, int count) {
this.maxChar = maxChar;
this.count = count;
}
public String toString() {
return String.format("<" + maxChar + "," + count + ">");
}
}
public static void main(String args[]) {
String str = "aaaaaaccde";
System.out.println(charactercountIndex(str));
}
}
You can create your own class that you will not be bounded to count of returned parameters from method.
public class MyCharacter {
private static int count;
private static char character;
private static int indexOf;
public void characterCountIndex(String str) {
int len = str.length();
for (int i = 0; i < len; i++) {
int cur_count = 1;
for (int j = i + 1; j < len; j++) {
if (str.charAt(i) != str.charAt(j))
break;
cur_count++;
}
if (cur_count > count) {
count = cur_count;
character = str.charAt(i);
indexOf = str.indexOf(character);
}
}
}
#Override
public String toString() {
return String.format("<%d, %d>", indexOf, count);
}
public static void main(String[] args) {
String str = "aaaaaaccde";
MyCharacter myCharacter = new MyCharacter();
myCharacter.characterCountIndex(str);
System.out.println(myCharacter);
}
}

Array index out of bounds exception. Please help if you can [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 5 years ago.
Extremely close to having this task finished but can't see which part of this is holding me back. If anybody could put me on the right track I'd be very thankful. the following is the error code that eclipse gives me each time I try to run this.
**Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -2
at lab01.EncodeDecode.backMap(EncodeDecode.java:162)
at lab01.EncodeDecode.Decode(EncodeDecode.java:68)
at lab01.EncodeDecode.(EncodeDecode.java:26)
at lab01.EncodeDecodeTester.main(EncodeDecodeTester.java:14)**
package lab01;
import java.util.*;
/**
*
* #author David Bierbrauer,
*
*/
public class EncodeDecode
{
//method declaration
static String[] originalList,encodedList,decodedList;
static int total;
public EncodeDecode(String[] oL)
{
//instance variable declaration
total = oL.length;
originalList = new String[total];
encodedList = new String[total];
decodedList = new String[total];
originalList = oL;
encodedList= Encode(originalList);
decodedList = Decode(encodedList);
}
public static String[] Encode (String[] originalList)
{
//declare control variables
String currentWord = "", codedWord = "";
char currentChar = ' ';
int i = 0, j = 0, stringLength = 0;
for (i=0; i < total ; i++)
{
currentWord = originalList[i];
stringLength = currentWord.length();
for (j = 0; j < stringLength; j++)
{
currentChar = currentWord.charAt(j);
codedWord = codedWord +forwardMap(currentChar);
}
encodedList[i] = codedWord;
codedWord = "";
}
return encodedList;
}
public static String[] Decode (String[] encodedList)
{
String currentWord = "", encodedWord = "";
char currentChar = ' ';
int i =0, j=0, stringLength = 0;
for(i = 0; i < total; i++)
{
currentWord = encodedList[i];
stringLength = currentWord.length();
for(j = 0; j < stringLength; j++)
{
currentChar = currentWord.charAt(j);
encodedWord = encodedWord + backMap(currentChar);
}
decodedList[i] = encodedWord;
encodedWord = "";
}
return decodedList;
}
public static char forwardMap(char currentChar)
{
char newChar = ' ';
int i = 0;
String encodeMapUpper = "CDEFGHIJKLMNOPQRSTUVWXYZAB";
String encodeMapLower = "cdefghijklmnopqrstuvwxyzab";
String encodeMapNumber = "2345678901";
char [] encodeArrayUpper = encodeMapUpper.toCharArray();
char [] encodeArrayLower = encodeMapLower.toCharArray();
char [] encodeArrayNumber = encodeMapNumber.toCharArray();
if(encodeMapUpper.indexOf(currentChar) != -1)
{
for( i = 0; i < encodeArrayUpper.length; i++)
{
if(currentChar == encodeArrayUpper[i])
{
newChar = encodeArrayUpper[(i+2) % 26];
}
}
}
else if(encodeMapLower.indexOf(currentChar) != -1)
{
for( i = 0; i < encodeArrayLower.length; i++)
{
if(currentChar == encodeArrayLower[i])
{
newChar = encodeArrayLower[(i+2) % 26];
}
}
}
else if(encodeMapNumber.indexOf(currentChar) != -1)
{
for( i = 0; i < encodeArrayNumber.length; i++)
{
if(currentChar == encodeArrayNumber[i])
{
newChar = encodeArrayNumber[(i+2) % 10];
}
}
}
else
{
//element is a special character
newChar = currentChar;
}
return newChar;
}
public static char backMap(char currentChar)
{
char newChar = ' ';
int i = 0;
String decodeMapUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String decodeMapLower = "abcdefghijklmnopqrstuvwxyz";
String decodeMapNumber = "0123456789";
char[] decodeArrayUpper = decodeMapUpper.toCharArray();
char[] decodeArrayLower = decodeMapLower.toCharArray();
char[] decodeArrayNumber = decodeMapNumber.toCharArray();
if (decodeMapUpper.indexOf(currentChar) != -1)
{
for (i=0; i < decodeArrayUpper.length; i++)
{
if (currentChar == decodeArrayUpper[i])
{
newChar = decodeArrayUpper[(i - 2) % 26];
}
}
}
else if(decodeMapLower.indexOf(currentChar) != -1)
{
for (i=0; i < decodeArrayLower.length; i++)
{
if (currentChar == decodeArrayLower[i])
{
newChar = decodeArrayLower[(i - 2) % 26];
}
}
}
else if(decodeMapNumber.indexOf(currentChar) != -1)
{
for (i=0; i < decodeArrayNumber.length; i++)
{
if (currentChar == decodeArrayNumber[i])
{
newChar = decodeArrayNumber[(i - 2) % 10];
}
}
}
else
{
newChar = currentChar;
}
return newChar;
}
//get methods
public String[] getEncodedList() { return encodedList;}
public String[] getDecodedList() { return decodedList;}
}
This is the tester class bellow just in case.
package lab01;
public class EncodeDecodeTester
{
public static void main(String[] args)
{
EncodeDecode testEncoder;
int x = 0;
String[] output = new String[5];
String[] oL = new String[] {"catdog","24","keys","Duck","PIZZA!"};
//create encoder
testEncoder = new EncodeDecode(oL);
System.out.println("Encoded list:");
for( x = 0; x < output.length; x++)
{
output = testEncoder.getEncodedList();
System.out.println(output[x]);
}
System.out.println();
System.out.println("Decoded List:");
for(x = 0; x < output.length; x++)
{
output = testEncoder.getDecodedList();
System.out.println(output[x] + " ");
}
System.out.println();
System.out.println("End");
}
}
Please help I am completely lost for words on what I did wrong here.
The Java % operator doesn't always produce a number between 0 and the second operand. Replace (i - 2) % 26 (which can produce -2) with (i + 24) % 26 and similarly in other places.

How to move each "i" in a string to the next position in java

I want to shift each i in a given string one index to the right. How can I do that? For example:
"Chit Nyein Oo is nothing.";
becomes
"Chti Nyeni Oo si nothnig.";
If i occurs in the last index, it need not change its position.
Use string.replaceAll
string.replaceAll("i(.)", "$1i");
DEMO
EDIT: NOW it works for all conditions. Last letter in the String is 'i' or not, it works.
public class t4 {
public static void main(String[] args) {
String input = "Chit Nyein Oo is nothing.";
char o = 'i';
int indexes = 0;
if(input.charAt(input.length()-1) != 'i'){ //Test if last letter is not 'i'
for (int i = 0; i < input.length(); i++) {
if(input.charAt(i) == o){
indexes++;
}
}
int []positions = new int[indexes];
for (int i = 0; i < input.length(); i++) {
if(input.charAt(i) == o){
positions[indexes-1] = i;
indexes--;
}
}
char[] characters = input.toCharArray();
for (int i = 0; i < positions.length; i++) {
if(characters[input.length()-1] != 'i'){
char temp = characters[positions[i]];
characters[positions[i]] = characters[positions[i]+1];
characters[positions[i]+1] = temp;
} else {
continue;
}
}
String swappedString = new String(characters);
System.out.println(input);
System.out.println(swappedString);
} else { //so last letter is i
char t = input.charAt(input.length()-1);
String ha = input.substring(0, input.length()-1);
input = ha;
for (int i = 0; i < input.length(); i++) {
if(input.charAt(i) == o){
indexes++;
}
}
int []positions = new int[indexes];
for (int i = 0; i < input.length(); i++) {
if(input.charAt(i) == o){
positions[indexes-1] = i;
indexes--;
}
}
char[] characters = input.toCharArray();
for (int i = 0; i < positions.length; i++) {
if(characters[input.length()-1] != 'i'){
char temp = characters[positions[i]];
characters[positions[i]] = characters[positions[i]+1];
characters[positions[i]+1] = temp;
} else {
continue;
}
}
String swappedString = new String(characters);
swappedString = swappedString + Character.toString(t);
System.out.println(input);
System.out.println(swappedString);
}
}
}
You can do this using a StringBuilder.
class Test {
public static void main(String[] args) {
String input = "Chit Nyein Oo is nothingi";
int len = input.length();
StringBuilder sb = new StringBuilder();
// System.out.println(sb);
for(int i=0; i<len; i++) {
char charAti = input.charAt(i);
if(charAti == 'i' && i<len-1) {
sb.append(input.charAt(i+1));
sb.append(charAti);
i++;
}
else {
sb.append(charAti);
}
}
System.out.println(sb);
}
}

how can i calculate the number of specific chars in a string?

Given a string how can i figure out the number of times each char in a string repeats itself
ex: aaaabbaaDD
output: 4a2b2a2D
public static void Calc() {
Input();
int count = 1;
String compressed = "";
for (int i = 0; i < input.length(); i++) {
if (lastChar == input.charAt(i)) {
count++;
compressed += Integer.toString(count) + input.charAt(i);
}
else {
lastChar = input.charAt(i);
count = 1;
}
}
System.out.println(compressed);
}
What you'r looking for is "Run-length encoding". Here is the working code to do that;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RunLengthEncoding {
public static String encode(String source) {
StringBuffer dest = new StringBuffer();
// iterate through input string
// Iterate the string N no.of.times where N is size of the string to find run length for each character
for (int i = 0; i < source.length(); i++) {
// By default run Length for all character is one
int runLength = 1;
// Loop condition will break when it finds next character is different from previous character.
while (i+1 < source.length() && source.charAt(i) == source.charAt(i+1)) {
runLength++;
i++;
}
dest.append(runLength);
dest.append(source.charAt(i));
}
return dest.toString();
}
public static String decode(String source) {
StringBuffer dest = new StringBuffer();
Pattern pattern = Pattern.compile("[0-9]+|[a-zA-Z]");
Matcher matcher = pattern.matcher(source);
while (matcher.find()) {
int number = Integer.parseInt(matcher.group());
matcher.find();
while (number-- != 0) {
dest.append(matcher.group());
}
}
return dest.toString();
}
public static void main(String[] args) {
String example = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
System.out.println(encode(example));
System.out.println(decode("1W1B1W1B1W1B1W1B1W1B1W1B1W1B"));
}
}
This program first finds the unique characters or numbers in a string. It will then check the frequency of occurance.
This program considers capital and small case as different characters. You can modify it if required by using ignorecase method.
import java.io.*;
public class RunLength {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
System.out.println("Please enter the string");
String str = br.readLine();//the input string is in str
calculateFrequency(str);
}
private static void calculateFrequency(String str) {
int length = str.length();
String characters[] = new String[length];//to store all unique characters in string
int frequency[] = new int[length];//to store the frequency of the characters
for (int i = 0; i < length; i++) {
characters[i] = null;
frequency[i] = 0;
}
//To get unique characters
char temp;
String temporary;
int uniqueCount = 0;
for (int i = 0; i < length; i++) {
int flag = 0;
temp = str.charAt(i);
temporary = "" + temp;
for (int j = 0; j < length; j++) {
if (characters[j] != null && characters[j].equals(temporary)) {
flag = 1;
break;
}
}
if (flag == 0) {
characters[uniqueCount] = temporary;
uniqueCount++;
}
}
// To get the frequency of the characters
for(int i=0;i<length;i++){
temp=str.charAt(i);
temporary = ""+temp;
for(int j=0;i<characters.length;j++){
if(characters[j].equals(temporary)){
frequency[j]++;
break;
}
}
}
// To display the output
for (int i = 0; i < length; i++) {
if (characters[i] != null) {
System.out.println(characters[i]+" "+frequency[i]);
}
}
}}
Some hints: In your code sample you also need to reset count to 0 when the run ends (when you update lastChar). And you need to output the final run (after the loop is done). And you need some kind of else or continue between the two cases.
#Balarmurugan k's solution is better - but just by improving upon your code I came up with this -
String input = "aaaabbaaDD";
int count = 0;
char lastChar = 0;
int inputSize = input.length();
String output = "";
for (int i = 0; i < inputSize; i++) {
if (i == 0) {
lastChar = input.charAt(i);
count++;
} else {
if (lastChar == input.charAt(i)) {
count++;
} else {
output = output + count + "" + lastChar;
count = 1;
lastChar = input.charAt(i);
}
}
}
output = output + count + "" + lastChar;
System.out.println(output);

Categories