Skip to content

Instantly share code, notes, and snippets.

@sreeprasad
Last active January 24, 2018 15:04
Show Gist options
  • Save sreeprasad/902863e6ebc0b8733136e4bfe7e2441f to your computer and use it in GitHub Desktop.
Save sreeprasad/902863e6ebc0b8733136e4bfe7e2441f to your computer and use it in GitHub Desktop.
package com.sreeprasad.algorithms;
import java.util.Stack;
public class RecommendedSequence {
private static StringBuilder recommended(String S) {
StringBuilder result = new StringBuilder();
if (S==null || S.length()==0) return result;
int N = S.length();
// this stack is to keep track of all the numbers.
// eg. in input 2[3[a]b], the numbers 2,3 goes to this stack.
Stack<Integer> st = new Stack<>();
// sb1 stores numbers or alphabets temporarily before processing
StringBuilder sb1 = new StringBuilder();
// counterOfOpenBrac is used to store number of '['.
// each time we see '[' counterOfOpenBrac increments.
// each time we see ']' counterOfOpenBrac decrements.
// every time counterOfOpenBrac becomes 0,
// we append the subResult to final result string AND flush the subResult.
int counterOfOpenBrac=0, i=-1;
// to store intermediary result.
StringBuilder subResult = new StringBuilder();
while (++i<N) {
sb1 = new StringBuilder();
// sb1 stores numbers or alphabets.
// this while loop stops running until we see '[' or ']' or end of string length.
while (i<N && isNumOrChar(S.charAt(i))) {
sb1.append(S.charAt(i++));
}
// if sb1 is a number, push number to stack.
if(isNotEmpty(sb1) && isNum(sb1)) {
st.push(Integer.parseInt(sb1.toString()));
}
// increment counterOfOpenBrac when we see '['
if (i< N && S.charAt(i)=='[') counterOfOpenBrac++;
// this is main core
if (i< N && S.charAt(i)==']' && isNotEmpty(sb1)) {
// v represents the number of times we have to multiply inner string.
// eg. for input 3[a] , v=3
int v = (!st.isEmpty()) ? st.pop() : 1;
counterOfOpenBrac--;
// sb2 is just to temporarily store results of multiplication
StringBuilder sb2 = new StringBuilder();
// keep multiplying and store in temp variable.
while (v>0) {
sb2.append(subResult).append(sb1);
v--;
}
// if counterOfOpenBrac is zero then means we have decompressed
// one substring completely. Hence store the decompressed string to final result
// and flush the subResult.
if (counterOfOpenBrac==0) {
// eg. for input 3[abc]2[ab], here we have completed decompressing 3[abc] to abcabcabc
// so store this decompressed string to final result.
result.append(sb2);
// We just completed processing 3[abc] part of the input.
// The input string still contains 2[ab] that needs to be processed.
subResult = new StringBuilder();
} else {
// reaching here means, this decompressed string needs to be
// stored in subResult and continue processing.
// eg. for input 3[2[a]b], after decompressing 2[a] to 'aa'
// do not write to final result. Instead store the decompressed string in
// subResult and continue processing.
subResult = new StringBuilder(sb2);
}
// flush the temporary store
// not sure if this is required.
sb1 = new StringBuilder();
} else if (i<N && st.isEmpty() && isNotEmpty(sb1)) {
// this is for edge case a[]b where there is no number and only chars
result.append(sb1);
sb1 = new StringBuilder();
}
}
// finally there may be chars at the end of the input string without any numbers
// eg. in input 3[abc]2[bc]c, 'c' is not associated with any number.
// so just append that to final result.
if (sb1.length()>0) result.append(sb1);
return result;
}
private static boolean isNotEmpty(StringBuilder sb1) {
return sb1!=null && sb1.length()>0;
}
public static void main(String[] args) {
//String S = "2[3[a]b]"; // tested.
String S = "3[abc]2[ab]c"; // tested.
//String S = "a[]b"; // tested.
//String S = "0[abc]"; // tested.
//String S = "10[a]"; // tested.
System.out.printf("input: %s\n",S);
System.out.printf("output: %s\n",recommended(S).toString());
}
// returns true if sb is a number else false
private static boolean isNum(StringBuilder sb) {
try {
Integer.parseInt(sb.toString());
} catch (NumberFormatException e){
return false;
}
return true;
}
private static boolean isNum(char c) {
return c>='0' && c<='9';
}
private static boolean isChar(char c) {
return c>='a' && c<='z';
}
private static boolean isNumOrChar(char c) {
//System.out.println("c "+c+" isNum(c) "+(isNum(c))+" isChar(c) "+(isChar(c)));
return isNum(c) || isChar(c);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment